Skip to content

New WSL sessions hang under memory pressure with vmbus_alloc_ring allocation failure #40795

Open

Description

@kuza55

AI disclosure

This report was drafted and filed with assistance from OpenAI Codex, based on local command output and logs from the affected machine.

Summary

WSL semi-routinely gets into a state where existing WSL shells continue to work, but new WSL sessions and Windows interop hang. This appears to correlate with memory pressure and a kernel vmbus_alloc_ring allocation failure.

This looks similar to #11612. It has similar outer symptoms to #12991, but Docker Desktop is already newer than the Docker Resource Saver fix discussed there and in docker/for-win#14656.

Environment

  • WSL 2
  • Distro: Ubuntu 24.04.3 LTS
  • Kernel: 6.18.33.1-microsoft-standard-WSL2
  • .wslconfig: memory=52GB
  • Docker Desktop: 4.44.3
  • Docker Engine / CLI: 28.3.2
  • Docker Compose: v2.39.1-desktop.1
  • Docker Desktop WSL bootstrap: 098d711f2ff00f0a1c4d69da1f9d6d2d
  • Windows / WSL app version: not collected while wedged because wsl.exe --status and wsl.exe -l -v hang

Behavior

After some time under normal dev workload, apparently under memory pressure:

  • existing WSL shells still run commands
  • opening new WSL terminals hangs
  • launching wsl.exe from WSL hangs
  • launching Windows interop commands such as cmd.exe /c echo cmd-ok from WSL hangs
  • recovery requires wsl --shutdown or restarting WSL services / rebooting

Relevant local checks

$ timeout 8 bash -lic 'printf shell-ok'
shell-ok

$ timeout 12 /mnt/c/Windows/System32/wsl.exe -d Ubuntu --exec /bin/bash -lc 'printf wsl-exec-ok'
<3>WSL (...) ERROR: UtilAcceptVsock:273: accept4 failed 110

$ timeout 10 /mnt/c/Windows/System32/wsl.exe --status
# timed out, no output

$ timeout 10 /mnt/c/Windows/System32/wsl.exe -l -v
# timed out, no output

$ timeout 8 /mnt/c/Windows/System32/cmd.exe /c echo cmd-ok
# timed out, no output

Journal excerpts

Repeated session leader failures:

Jun 12 10:04:35 ... WSL (849628 - SessionLeader) ERROR: UtilAcceptVsock:273: accept4 failed 110
Jun 12 10:04:35 ... WSL (849628 - SessionLeader) ERROR: operator():1263: UtilAcceptVsock() failed for session leader 110
Jun 12 10:04:44 ... WSL (849732 - SessionLeader) ERROR: UtilAcceptVsock:273: accept4 failed 110
Jun 12 10:04:44 ... WSL (849732 - SessionLeader) ERROR: operator():1263: UtilAcceptVsock() failed for session leader 110
Jun 12 15:47:51 ... WSL (1042443 - SessionLeader) ERROR: UtilAcceptVsock:273: accept4 failed 110
Jun 12 15:47:51 ... WSL (1042443 - SessionLeader) ERROR: operator():1263: UtilAcceptVsock() failed for session leader 110
Jun 12 17:10:40 ... WSL (1059662 - SessionLeader) ERROR: UtilAcceptVsock:273: accept4 failed 110
Jun 12 17:10:40 ... WSL (1059662 - SessionLeader) ERROR: operator():1263: UtilAcceptVsock() failed for session leader 110

Earlier memory / Hyper-V socket allocation failure:

Jun 11 17:40:07 ... kernel: kworker/0:0: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
Jun 11 17:40:07 ... kernel: Workqueue: hv_pri_chan vmbus_add_channel_work
Jun 11 17:40:07 ... kernel:  vmbus_alloc_ring+0x78/0xd0
Jun 11 17:40:07 ... kernel:  vmbus_open+0x29/0x80
Jun 11 17:40:07 ... kernel:  hvs_probe+0x1f4/0x4c0
Jun 11 17:40:07 ... kernel:  vmbus_probe+0x42/0xa0
Jun 11 17:40:07 ... kernel:  vmbus_device_register+0x87/0x130
Jun 11 17:40:07 ... kernel:  vmbus_add_channel_work+0x146/0x1d0

Mem-Info from the same allocation failure showed heavy pressure near the WSL memory cap:

active_anon:114025 inactive_anon:11507801 isolated_anon:32
active_file:1031583 inactive_file:146747 isolated_file:0
free:60986 free_pcp:1372 free_cma:0
Node 0 active_anon:456100kB inactive_anon:46031204kB active_file:4126332kB inactive_file:586988kB
Node 0 Normal free:46896kB min:41688kB low:91140kB high:140592kB
Node 0 Normal: ... 0*512kB 0*1024kB 0*2048kB 0*4096kB = 44724kB
Free swap  = 12716576kB
Total swap = 13631488kB

The same allocation failure repeated at least two more times:

Jun 11 17:41:42 ... kernel: kworker/0:3: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO)
Jun 11 17:41:42 ... kernel: Workqueue: hv_pri_chan vmbus_add_channel_work
Jun 11 17:41:42 ... kernel:  vmbus_alloc_ring+0x78/0xd0
Jun 11 17:41:58 ... kernel: kworker/0:2: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO)
Jun 11 17:41:58 ... kernel: Workqueue: hv_pri_chan vmbus_add_channel_work
Jun 11 17:41:58 ... kernel:  vmbus_alloc_ring+0x78/0xd0

Notes

Docker Desktop is installed and WSL integration is active, but the installed Docker Desktop version is 4.44.3, newer than the 4.42.1 fix referenced from #12991 / docker/for-win#14656. This may still be Docker-triggered, but the local kernel evidence looks closer to #11612: vmbus_alloc_ring cannot allocate under memory pressure, then WSL session creation / interop starts timing out.

Activity

  1. github-actions commented on Jun 12, 2026

    @github-actions
    Contributor

    Logs are required for review from WSL team

    If this a feature request, please reply with '/feature'. If this is a question, reply with '/question'.
    Otherwise, please attach logs by following the instructions below, your issue will not be reviewed unless they are added. These logs will help us understand what is going on in your machine.

    How to collect WSL logs

    Download and execute collect-wsl-logs.ps1 in an administrative powershell prompt:

    Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/collect-wsl-logs.ps1" -OutFile collect-wsl-logs.ps1
    Set-ExecutionPolicy Bypass -Scope Process -Force
    .\collect-wsl-logs.ps1
    

    The script will output the path of the log file once done.

    If this is a networking issue, please use .\collect-wsl-logs.ps1 -LogProfile networking instead, following the instructions in Collect WSL logs for networking issues

    Once completed please upload the output files to this GitHub issue.

    See Collect WSL logs (recommended method).

    If you choose to email these logs instead of attaching them to the bug, please send them to wsl-gh-logs@microsoft.com with the GitHub issue number in the subject, and include a link to your GitHub issue comment in the message body, and reply with '/emailed-logs'.

  2. kuza55 commented on Jun 12, 2026

    @kuza55
    Author

    /emailed-logs

  3. github-actions commented on Jun 12, 2026

    @github-actions
    Contributor
    Diagnostic information
    Found '/emailed-logs', adding tag 'emailed-logs'
    
  4. chemwolf6922 commented on Jun 15, 2026

    @chemwolf6922
    Contributor

    Hi kuza55 , I'm working on a fix for this. #40519.

    If you would like to. Could you please try out this build: https://github.com/chemwolf6922/build-wsl/actions/runs/27520782738/artifacts/7628123738 to see if it resolves the issue? Thanks.
    The build is at this commit: d41e13d

    Please note this is a dev build. And may contain other issues. It's recommended to return to a released version after the test.

  5. SeanIsTyping commented on Jun 30, 2026

    @SeanIsTyping

    I encountered something similar running Podman and a PostgreSQL container. Already established connection continued running normally, and the guest Podman machine stays in the running state, but eventually no new connections to the database can be established, and most WSL commands will hang or return the Wsl/Service/0x80072747 error.

    dmesg
    [Jun29 16:14] Linux version 6.6.114.1-microsoft-standard-WSL2 (root@507f3e43091d) (gcc (GCC) 13.2.0, GNU ld (GNU Binutils) 2.41) #1 SMP PREEMPT_DYNAMIC Mon Dec  1 20:46:23 UTC 2025
    ...
    [Jun29 16:24] mini_init (267): drop_caches: 1
    [Jun29 21:34] mini_init (267): drop_caches: 1
    [Jun30 03:33] kworker/0:2: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
    [  +0.000694] CPU: 0 PID: 231458 Comm: kworker/0:2 Not tainted 6.6.114.1-microsoft-standard-WSL2 #1
    [  +0.000331] Workqueue: hv_pri_chan vmbus_add_channel_work
    [  +0.000360] Call Trace:
    [  +0.000111]  <TASK>
    [  +0.000198]  dump_stack_lvl+0x4c/0x70
    [  +0.000344]  dump_stack+0x14/0x20
    [  +0.000150]  warn_alloc+0x10d/0x180
    [  +0.000285]  ? __alloc_pages_direct_compact+0x19a/0x290
    [  +0.000196]  __alloc_pages_slowpath.constprop.0+0xde2/0xee0
    [  +0.000225]  ? kmalloc_trace+0x2e/0xa0
    [  +0.000306]  __alloc_pages+0x30c/0x340
    [  +0.000239]  vmbus_alloc_ring+0x79/0xd0
    [  +0.000165]  ? __pfx_hvs_channel_cb+0x10/0x10
    [  +0.000382]  vmbus_open+0x29/0x80
    [  +0.000252]  ? vsock_assign_transport+0x1e4/0x260
    [  +0.000206]  hvs_probe+0x27f/0x4b0
    [  +0.000337]  vmbus_probe+0x3f/0xa0
    [  +0.000133]  really_probe+0x1a7/0x3f0
    [  +0.000413]  ? __pfx___device_attach_driver+0x10/0x10
    [  +0.000184]  __driver_probe_device+0x7d/0x170
    [  +0.000298]  driver_probe_device+0x24/0xa0
    [  +0.000094]  __device_attach_driver+0x98/0x120
    [  +0.000154]  bus_for_each_drv+0x88/0xe0
    [  +0.000145]  __device_attach+0xb6/0x1c0
    [  +0.000148]  device_initial_probe+0x17/0x20
    [  +0.000120]  bus_probe_device+0x9d/0xa0
    [  +0.000134]  device_add+0x694/0x8a0
    [  +0.000108]  ? hrtimer_init+0x2b/0x80
    [  +0.000223]  device_register+0x1e/0x30
    [  +0.000119]  vmbus_device_register+0x87/0x130
    [  +0.000150]  vmbus_add_channel_work+0x146/0x1d0
    [  +0.000171]  process_one_work+0x18e/0x3a0
    [  +0.000189]  worker_thread+0x285/0x3c0
    [  +0.000129]  ? _raw_spin_unlock_irqrestore+0x12/0x40
    [  +0.000193]  ? __pfx_worker_thread+0x10/0x10
    [  +0.000310]  kthread+0xf3/0x130
    [  +0.000167]  ? __pfx_kthread+0x10/0x10
    [  +0.000104]  ret_from_fork+0x3e/0x60
    [  +0.000159]  ? __pfx_kthread+0x10/0x10
    [  +0.000132]  ret_from_fork_asm+0x1b/0x30
    [  +0.000124]  </TASK>
    [  +0.000108] Mem-Info:
    [  +0.000079] active_anon:232555 inactive_anon:132037 isolated_anon:0
                   active_file:106161 inactive_file:368398 isolated_file:0
                   unevictable:0 dirty:43986 writeback:0
                   slab_reclaimable:21459 slab_unreclaimable:23865
                   mapped:274954 shmem:253815 pagetables:6324
                   sec_pagetables:0 bounce:0
                   kernel_misc_reclaimable:0
                   free:19192 free_pcp:166 free_cma:0
    [  +0.001290] Node 0 active_anon:930220kB inactive_anon:530344kB active_file:424644kB inactive_file:1473956kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:1099816kB dirty:175944kB writeback:0kB shmem:1015260kB shmem_thp:0kB shmem_pmdmapped:0kB anon_thp:0kB writeback_tmp:0kB kernel_stack:6144kB pagetables:25296kB sec_pagetables:0kB all_unreclaimable? no
    [  +0.001103] Node 0 DMA32 free:72472kB boost:0kB min:44912kB low:56140kB high:67368kB reserved_highatomic:0KB active_anon:930212kB inactive_anon:531784kB active_file:424580kB inactive_file:1474528kB unevictable:0kB writepending:175940kB present:4061820kB managed:3888204kB mlocked:0kB bounce:0kB free_pcp:812kB local_pcp:0kB free_cma:0kB
    [  +0.001436] lowmem_reserve[]: 0 11 11 11
    [  +0.000136] Node 0 Normal free:256kB boost:0kB min:140kB low:172kB high:204kB reserved_highatomic:0KB active_anon:8kB inactive_anon:24kB active_file:64kB inactive_file:68kB unevictable:0kB writepending:4kB present:24576kB managed:12276kB mlocked:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
    [  +0.002120] lowmem_reserve[]: 0 0 0 0
    [  +0.000155] Node 0 DMA32: 3955*4kB (UE) 2006*8kB (UME) 614*16kB (UME) 186*32kB (UME) 98*64kB (UME) 44*128kB (UM) 29*256kB (U) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 66972kB
    [  +0.000385] Node 0 Normal: 23*4kB (U) 15*8kB (U) 3*16kB (U) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 260kB
    [  +0.000453] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
    [  +0.000378] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
    [  +0.000261] 730002 total pagecache pages
    [  +0.000107] 776 pages in swap cache
    [  +0.000115] Free swap  = 989628kB
    [  +0.000124] Total swap = 1048576kB
    [  +0.000123] 1021599 pages RAM
    [  +0.000093] 0 pages HighMem/MovableOnly
    [  +0.000113] 46479 pages reserved
    [  +0.000339] 0 pages hwpoisoned
    [Jun30 03:34] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [  +6.648816] mini_init (267): drop_caches: 1
    [Jun30 03:35] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:36] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:37] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:38] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:39] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:40] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:41] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:42] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    [Jun30 03:43] WSL (230847 - Relay) ERROR: UtilAcceptVsock:246: Waiting for abnormally long accept(10)
    ...
    

    Increasing the ram limit in wslconfig to 8G does not help either. The same errors pops up after running the container for a day.

  6. exnavi commented on Sep 14, 2026

    @exnavi

    Additional related observations from a Windows 10 / WSL host; seeking guidance before changing the system.

    Environment: Windows 10 Home 22H2, build 19045.7725; WSL 2.7.12.0; kernel 6.18.33.2-microsoft-standard-WSL2; 7.87 GiB visible host RAM, 3.76 GiB guest RAM, 1 GiB guest swap.

    Retained current-boot warnings show:

    • Order-7 VMBus ring allocation failure with GFP_KERNEL|__GFP_ZERO. At that failure, DMA32 had no blocks >=256 KiB and Normal no blocks >=128 KiB.
    • Order-4 p9_fcall_init / p9_client_readdir allocation failures with GFP_NOFS|__GFP_COMP. On one failure DMA32 was below its boosted minimum while some larger blocks remained, so lack of total free memory alone is not the full description.
    • Windows interop subsequently reported UtilAcceptVsock: accept4 failed 110, while an existing Linux session continued working.

    Later validated native Windows memory APIs measured 95% physical-memory load with about 384.5 MiB available and commit below its limit, near further allocation warnings. A later owner-local process snapshot showed vmmem as the largest working set (3.45 GiB); this was not synchronized with the failures. A Windows-backed directory scan also returned ENOMEM. An earlier passive interval was quiet and inconclusive. We have not established a relay leak or attributed the unavailable contiguous pages to a particular allocation owner.

    Source comparison finds drivers/hv/channel.c identical between kernel tags linux-msft-wsl-6.18.33.2 and linux-msft-wsl-6.18.40.1, with p9_fcall_init and p9_client_readdir unchanged. This does not rule out indirect fixes elsewhere. WSL 2.7.14's process-accept call still lacks the explicit timeout added by PR #41252.

    Is there an identified supported remedy for this combination, or a minimally scoped failure-time measurement that distinguishes ordinary capacity/fragmentation pressure from retained kernel/channel allocations? We are not assuming more swap, RAM or a stable update fixes it. No raw logs, private filenames or workload data are included here.

    Prepared with coding-assistant assistance from retained local measurements; reviewed findings are limited as stated.

  7. emersonbusson commented on Sep 17, 2026

    @emersonbusson

    Technical Resolution & Reference Kernel Patches for Order-7 VMBus Ring Failures

    Regarding the vmbus_alloc_ring Order-7 allocation failures and UtilAcceptVsock: accept4 failed 110 timeouts under memory pressure:

    We encountered and systematically resolved this exact failure pattern on WSL2 (Kernel 6.18.40.1).

    Root Cause:

    vmbus_alloc_ring() requests contiguous physical pages via alloc_pages(..., order: 7) (512 KiB). As developer workflows run, physical memory fragmentation depletes orders 7 through 10 in /proc/buddyinfo, even when several gigabytes of memory remain free across lower orders (orders 0–3). When the contiguous allocation fails, synthetic channel creation aborts, hanging the HCS session handshake.

    Tested Solution:

    We implemented and validated a clean, two-part kernel resilience fix:

    1. Virtual Ring Buffer Fallback (drivers/hv/ring_buffer.c, drivers/hv/channel.c):
      When alloc_pages(order: 7) fails, vmbus_alloc_ring immediately falls back to vzalloc(). In vmbus_establish_gpa_range(), the virtually mapped pages are translated to PFNs via vmalloc_to_page(). Because the Hyper-V host natively supports scattered PFNs in the GPA descriptor, this requires zero host-side changes and establishes channels in ≤ 0.15 ms under heavy fragmentation. Confidential VM (CoCo) memory isolation is strictly preserved.
    2. VMBus Headroom & Balloon Backpressure (drivers/hv/hv_common.c, drivers/hv/hv_balloon.c):
      Guarantees 512 MiB dynamic atomic headroom and defers host balloon inflation (si_mem_available() < totalram_pages() / 32) during active direct reclaim.

    Empirical Verification & Tested Tree:

    Tested under sustained 99% RAM load with PASS_ZERO_PANIC and zero session timeouts. The full reference implementation, patches, and deployment instructions are available on:
    👉 emersonbusson/WSL2-Linux-Kernel (branches linux-msft-wsl-6.18.y and feature/ramshared-wsl2-resilience-6.18).

  8. Hugo-Polloli commented on Sep 22, 2026

    @Hugo-Polloli

    I have observed this recurring on WSL 2.9.12.0 / kernel 6.18.40.1-microsoft-standard-WSL2, after upgrading from 2.6.3 and rebooting. This may help distinguish this allocation failure from the indefinite relay-accept lifetime fixed by #41252.

    Environment: Windows 11 build 26200.9457; Ubuntu 22.04.5; 64 GB host RAM; .wslconfig memory=32GB, swap=8GB, networkingMode=mirrored. Docker Desktop integration and concurrent data-processing/development workloads are active. No synthetic memory stress test was run.

    The first order-7 failure I captured in vmbus_alloc_ring occurred about 41 minutes into the new boot. Later retained kernel output contains repeated order-7 ring allocation failures and UtilAcceptVsock: accept4 failed 110, plus order-4 Plan9 p9_fcall_init failures during ordinary Git reads. Existing Linux commands continue to work. The earlier first-failure excerpt was saved before the kernel ring buffer rotated.

    Evidence from a failure at uptime 9113 seconds:

    kworker/0:2: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO)
    Workqueue: hv_pri_chan vmbus_add_channel_work
    vmbus_alloc_ring -> vmbus_open -> hvs_probe
    DMA32: ... 15*256kB ... 0*512kB 0*1024kB 0*2048kB 0*4096kB
    Normal: ... 7*256kB ... 0*512kB 0*1024kB 0*2048kB 0*4096kB
    

    A nearby, separately sampled /proc/meminfo showed approximately 26 GiB MemAvailable out of 31.35 GiB, dominated by buffers/file cache and reclaimable slab, with only about 250 MiB MemFree. I did not take this snapshot atomically with the failure. A retained order-4 failure also showed no blocks >=64 KiB in either zone. Cgroup accounting attributes most file-cache/metadata charge to two active data-processing services, with relatively small anonymous memory. I have not established which allocations prevent compaction or a specific triggering workload.

    In a later process-tree inspection, I found six relay processes, each still parented to a SessionLeader and with a child. A briefly observed unsuffixed Relay was young and had a live parent. This differs from the hours-old orphaned relays observed on the previous 2.6.3 boot; it does not exclude every possible channel/resource leak. wsl-user/memory.events had zero max/oom/oom_kill events, and the guest OOM-kill counter was zero. compaction_proactiveness read as 0; it was not changed.

    In the exact running kernel tag, vmbus_alloc_ring attempts a contiguous allocation on the target node and then via alloc_pages, returning ENOMEM if both fail. The process-accept timeout fix therefore does not by itself remove this failure mode. This is an observed allocation mechanism, not a claim that I have proved the complete cause of fragmentation.

    I have since stopped the two data-processing services and the associated materializer, preserving their data. Their cached pages remain resident after exit; this is not yet a controlled demonstration of recovery or workload causation. I have not restarted them or run a cache-drop experiment.

    Is there an official kernel fix planned for this case, or a preferred bounded diagnostic to identify why reclaim/compaction cannot satisfy these requests under cache-heavy workloads? I have not installed a custom kernel, dropped caches, changed VM tuning, or killed relay processes.

    I prepared this with Codex assistance from local measurements and tagged source inspection. I have included only selected technical measurements and omitted raw private logs and workload identifiers.

  9. ManthanVasani commented on Sep 24, 2026

    @ManthanVasani

    TL;DR: For connections the host opens into WSL init's listeners (session leader, wsl.exe stdio, interop), the order-7 ring is not inherent to hv_sock. It is sized from the listening socket's buffers, which WSL never sets, so it follows net.core.wmem_default (212992: 52 + 52 pages, order 7). At 28672 the same connections need order 4. After that change, all 2,114 traced rings at the new size succeeded (the Plan 9 server, which sets its own 131072, still failed 5 of 51), and 294/294 interop calls succeeded, 84 of them with no free block of order 7 or larger. PR: #41690.

    Environment: WSL 2.7.3.0, kernel 6.6.114.1-microsoft-standard-WSL2, Windows 11 build 26200, networkingMode=mirrored, autoMemoryReclaim=gradual, 25 GB guest memory, 8 GB swap.

    Where the order 7 comes from

    Measurement

    Workaround, runtime only: sudo sysctl -w net.core.wmem_default=28672 net.core.rmem_default=28672. I traced every vmbus_alloc_ring() with a kprobe (commands below):

    Window Ring (each direction) Allocations Failed (-12)
    Before (~6 min) 212992 41 1
    After (~5.2 h) 28672 2,114 0
    After 212992 0 n/a
    Plan 9 server, before / after 131072 2 / 51 0 / 5
    • After the change, a once-a-minute cmd.exe /c ver passed 294/294. /proc/buddyinfo, read just before each run, showed no free block of order 7 or larger in DMA32 or Normal for 84 of them (64 KB+ blocks in those runs: 16 at the lowest, median about 480).
    • The kernel log has 32 order-7 hvs_probe failures in the ~5 h before the change (longest gap 90 min) and none in the ~5.2 h after. It is rate-limited, so the trace is the stronger evidence.
    • 28672 is 7 + 7 pages on 6.6 and 8 + 8 on 6.18: order 4 on both.

    Limits of the workaround

    • Only listeners created afterwards pick it up. A file in /etc/sysctl.d/ misses the interop listener created at distro start. kernelCommandLine = sysctl.net.core.wmem_default=28672 sysctl.net.core.rmem_default=28672 under [wsl2] should cover it, since sysctl.* parameters apply before /init (main.c#L1478-L1481). I have not yet verified that after a restart.
    • It is global. UDP and netlink receive buffers shrink, and AF_UNIX datagrams over ~28 KB fail with EMSGSIZE (af_unix.c#L1989). Bulk hv_sock paths also get small rings: wsl.exe and interop stdio, which init: size hvsocket listener buffers so host-initiated connections avoid order-7 ring allocations #41690 shrinks too (its throughput cost is still to be measured; see the PR), wsl --export/--import, and with kernelCommandLine the NAT-mode localhost relay, which init: size hvsocket listener buffers so host-initiated connections avoid order-7 ring allocations #41690 leaves alone. TCP is unaffected.
    • The Plan 9 server sizes itself (65536, doubled to 131072, order 6: plan9.cpp#L248-L254), so 9P connections from Windows can still fail at order 6. Each of its 5 failures had a matching order:6 warning from hvs_probe, and each came milliseconds after 28672 rings in the same burst had succeeded.
    • Order 4 is the floor, not immunity. The 6-page minimum makes it the smallest ring hv_sock requests. The order-4 9P client failures reported above (p9_fcall_init, readdir buffers) continued, at least 20 since the change, while every 28672 ring succeeded.

    Proposed fix

    Reproducing the ring size (as root)

    T=/sys/kernel/tracing
    echo 'p:hvring vmbus_alloc_ring send=$arg2:u32 recv=$arg3:u32' >> $T/kprobe_events
    echo 'r:hvringret vmbus_alloc_ring ret=$retval:s32' >> $T/kprobe_events
    echo 1 > $T/events/kprobes/hvring/enable; echo 1 > $T/events/kprobes/hvringret/enable
    cat $T/trace_pipe    # then, in another shell: /mnt/c/Windows/System32/cmd.exe /c ver
    # cleanup
    echo 0 > $T/events/kprobes/hvring/enable; echo 0 > $T/events/kprobes/hvringret/enable
    echo '-:hvringret' >> $T/kprobe_events; echo '-:hvring' >> $T/kprobe_events

    Any machine shows the ring size; ret=-12 needs fragmented memory. To undo the workaround, run the same sysctl with 212992 (new sockets only).

  10. emersonbusson commented on Sep 24, 2026

    @emersonbusson

    I am following up on this report and Michael Kelley's September 22 review of my [PATCH 2/2] hv: vmbus: add virtual memory fallback for ring buffer allocations under memory pressure email thread.

    I am preparing a kernel-side change that routes VMBus ring allocation through the existing vmbus_alloc_buffer() mechanism, with chunked allocation and per-chunk Confidential VM handling. The direction matches the review's suggestion to use that mechanism for rings and keep buffer/GPADL lifetime state together. This is still a local draft; it has not been submitted, and fault-injection plus GPADL teardown and CoCo validation remain outstanding. I am not claiming that the issue has been reproduced or fixed by this draft.

    I also noticed the related WSL PR #41690, which reduces ring sizes for selected host-initiated hv_sock listeners. That is a useful, narrower mitigation for those WSL control and stdio paths. The kernel allocator change has a broader intended scope across VMBus ring users; the two approaches should be coordinated so the kernel series complements the WSL listener change rather than duplicates its coverage.

  11. ManthanVasani commented on Sep 24, 2026

    @ManthanVasani

    EMERSON BUSSON (@emersonbusson) Thanks, agreed they complement each other. #41690 shrinks the rings of most of WSL's control and stdio listeners and needs no kernel change, so it helps on the 6.6 and 6.18 kernels WSL ships now. Allocating rings through vmbus_alloc_buffer() would also cover what #41690 leaves alone: the Plan 9 server (order 6), and the bulk relays and WSLC thread forks (order 7). vmbus_alloc_buffer() is in mainline only since 7.3-rc1, so it needs a backport to reach WSL's kernels; after that, #41690 still cuts the control and stdio rings from 208 KB to 28 KB per direction (32 KB on 6.18).

    The hv_sock sizing idea from my comment above (listeners that set no SO_SNDBUF/SO_RCVBUF have kept wmem_default/rmem_default since c0cfa2d8a788) is in net/vmw_vsock/hyperv_transport.c, so it would be a small hv_sock patch of its own rather than part of the VMBus series. It would also shrink WSL's bulk listeners to 24 KB rings (28 KB on 6.18), so WSL would need to size those explicitly to keep their throughput, and your change is what would let them keep large rings without needing contiguous memory.

  12. visa360-org commented on Oct 15, 2026

    @visa360-org

    Another data point, on the latest release: WSL 3.0.3.0, kernel 6.18.54.1-microsoft-standard-WSL2, Windows 10.0.26200.9711. Same trace as the report, and what we measured matches ManthanVasani's analysis above (the ring is sized from the listener's default socket buffers).

    Setup: .wslconfig sets only memory=5GB and swap=8GB (guest MemTotal 4919 MiB, 8 vCPUs, Ubuntu with systemd). Load: two or three parallel sessions running a Node/TypeScript monorepo build and its test suites (type-checking, unit tests, browser tests with Chromium).

    Frequency: 11 order-7 failures in about 15 hours, 2026-10-14 17:21 to 2026-10-15 08:43 (UTC+8; wall times converted from the kernel's monotonic clock), over three VM boots:

    • VM 1: 17:21:15, 18:46:45, 19:07:59, 20:41:00, and four at 21:03:57–58 during wsl --shutdown
    • VM 2: 22:17:01 and 01:31:07
    • VM 3: 08:43:30

    Each one was followed 30 s later by UtilAcceptVsock ... accept4 failed 110 from a Relay or SessionLeader, and wsl.exe failed with Wsl/Service/WSAETIMEDOUT, while the sessions already open kept running. Two of them fell inside long hangs (about 100 and 70 minutes, both ended with wsl --shutdown) under heavy memory pressure: swap full in one, 5.8 of 8 GB used in the other. But at 18:46:45 the 8 GB swap was still unused, and 08:43:30 was fragmentation alone, with 1.8 GB of page cache, 2.5 GB anon, swap almost unused and no free block above 256 KiB:

    2026-10-15T08:43:30+08:00 <host> kernel: kworker/0:1: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0
    <host> kernel: CPU: 0 UID: 0 PID: 23446 Comm: kworker/0:1 Not tainted 6.18.54.1-microsoft-standard-WSL2 #1 PREEMPT(none)
    <host> kernel: Workqueue: hv_pri_chan vmbus_add_channel_work
    <host> kernel:  __alloc_pages_noprof+0x12/0x30
    <host> kernel:  vmbus_alloc_ring+0x78/0xd0
    <host> kernel:  vmbus_open+0x29/0x80
    <host> kernel:  hvs_probe+0x1f6/0x4c0
    <host> kernel:  vmbus_probe+0x42/0xa0
    ...
    <host> kernel: Node 0 DMA32 free:86428kB boost:0kB min:35776kB low:44720kB high:53664kB ...
    <host> kernel: Node 0 Normal free:21160kB boost:0kB min:9276kB low:11592kB high:13908kB ...
    <host> kernel: Node 0 DMA32: 3846*4kB (UME) 2239*8kB (UME) 857*16kB (UME) 565*32kB (UME) 174*64kB (UME) 44*128kB (UME) 18*256kB (UME) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 86464kB
    <host> kernel: Node 0 Normal: 511*4kB (UMEH) 706*8kB (UMEH) 267*16kB (UMEH) 172*32kB (UMEH) 38*64kB (UMH) 9*128kB (UMH) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 21052kB
    <host> kernel: Free swap  = 8232996kB
    <host> kernel: Total swap = 8388608kB
    2026-10-15T08:44:00+08:00 <host> unknown: WSL (65225 - Relay) ERROR: UtilAcceptVsock:281: accept4 failed 110
    

    Ring size: with the default net.core.wmem_default/rmem_default of 212992, the channels of each new session showed write_avail=208896 (/sys/bus/vmbus/devices/*/channels/*/write_avail): two 208 KiB rings, one order-7 block. As expected while #41690 is still open.

    Mitigation applied (guest only, no restart): /etc/sysctl.d/99-wsl-hvsock.conf, loaded with sysctl --system:

    net.core.rmem_default = 65536
    net.core.wmem_default = 65536
    vm.min_free_kbytes = 131072
    vm.watermark_scale_factor = 200
    vm.compaction_proactiveness = 50
    

    First effect:

    • Channels opened by a new wsl.exe session after the change show write_avail=61440 (64 KiB rings, an order-5 block). So do the four channels of an interop call (a Windows exe started from the guest), in a distro run that had started before the change. Channels opened earlier keep 208896.
    • The Plan 9 channel stays at 126976, since it sizes its own buffer (order 6, as noted above).
    • The higher watermarks cost about 410 MiB of MemAvailable (4,264,168 kB to 3,842,500 kB at the moment of applying).
    • No allocation failure since then, but it has only run for minutes, so it is too early to say whether it prevents a recurrence. The sysctl can't reach the Plan 9 server, which sizes its own buffer; that path still needs the kernel-side fix.

    Investigated and drafted by Claude Code (claude-opus-5-5) on behalf of the reporter.

  13. 0xdhx commented on Oct 31, 2026

    @0xdhx

    Adding a contributing cause for anyone here who also runs Docker Desktop: on the WSL2 backend it turns off both of the kernel's background anti-fragmentation mechanisms for the whole VM, which makes these order-7 failures much more likely.

    Docker Desktop's init daemon in the docker-desktop distro (docker-desktop.iso:/initd, 4.97.0) writes a sysctl table into the shared kernel at every start, after the user distro's systemd-sysctl. It includes:

    vm.compaction_proactiveness = 0      # kernel default 20
    vm.watermark_boost_factor   = 0      # kernel default 15000
    

    So in every distro on the machine, proactive compaction is off and the watermark boost that normally reacts to fragmentation events never fires. On WSL 3.0.3.0 / kernel 6.18.54.1 with Docker running, all 222 order-7 failure reports in one boot show Normal ... boost:0kB, and at failure the Normal zone often had hundreds of MiB (once 11 GB) free with no block of order 7 or larger. That is fragmentation, not a shortage of memory. One failure from this morning:

    01:10:46 kworker/0:0: page allocation failure: order:7, mode:0xdc0(GFP_KERNEL|__GFP_ZERO)
    01:11:16 WSL (228281 - SessionLeader) ERROR: UtilAcceptVsock:281: accept4 failed 110
    

    Check with sysctl vm.compaction_proactiveness vm.watermark_boost_factor; 0 0 while Docker Desktop is running is this. A /etc/sysctl.d file alone does not hold, because Docker writes after it; re-applying it on a timer (systemd-sysctl every few minutes) does, until the next Docker start. Reported to Docker as docker/desktop-feedback#809.

    This complements rather than replaces the listener-sizing fix in #41690: Docker's settings only remove the kernel's defences, while the order-7 request itself comes from the unsized listeners described above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions