<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Windows guests destroyed by PoD exhaustion with Citrix tools — XCP-ng tools fix it, but XO gives no warning either way]]></title><description><![CDATA[<p dir="auto"><strong>Hello Folks,</strong></p>
<p dir="auto">Posting this because it cost me an evening and was misattributed to four different subsystems before I found it, and because I think the fix and the reporting gap are separable questions.</p>
<h2>Summary</h2>
<p dir="auto">Windows Server 2022 guests on XCP-ng 8.3 were being destroyed and restarted every 12–15 minutes. No bugcheck, no dump, nothing in the Windows event log except event 41 / 6008 — "rebooted without cleanly shutting down."</p>
<p dir="auto">The cause was populate-on-demand exhaustion:</p>
<pre><code>(XEN) p2m_pod_demand_populate: Dom124 out of PoD memory! (tot=1049115 ents=3145696 dom0)
(XEN) domain_crash called from p2m_pod_demand_populate+0x4e2/0x8c0
</code></pre>
<p dir="auto">The VMs had <code>memory-static-max</code> at 16 GiB with <code>memory-dynamic-max</code> at 4 GiB. Xen backs the dynamic amount and populates the rest on demand, relying on the balloon driver to return pages before the pool runs dry.</p>
<p dir="auto"><strong>The balloon driver in the Citrix XenServer VM Tools 9.4.0 does not reclaim under that pressure.</strong><br />
Replacing them with XCP-ng Windows Guest Tools 9.1.200.0 fixed it completely.</p>
<h2>The test</h2>
<p dir="auto">Two VMs from the same sysprepped Server 2022 template, same host, identical memory configuration, differing only in guest tools.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>Arm A</th>
<th>Arm B</th>
</tr>
</thead>
<tbody>
<tr>
<td>Guest tools</td>
<td>Citrix XenServer VM Tools 9.4.0</td>
<td>XCP-ng Windows Guest Tools 9.1.200.0</td>
</tr>
<tr>
<td><code>memory-static-max</code></td>
<td>17179869184 (16 GiB)</td>
<td>17179869184 (16 GiB)</td>
</tr>
<tr>
<td><code>memory-dynamic-max</code></td>
<td>4294967296 (4 GiB)</td>
<td>4294967296 (4 GiB)</td>
</tr>
<tr>
<td><code>memory-dynamic-min</code></td>
<td>4294967296 (4 GiB)</td>
<td>4294967296 (4 GiB)</td>
</tr>
<tr>
<td><code>memory-static-min</code></td>
<td>1073741824 (1 GiB)</td>
<td>1073741824 (1 GiB)</td>
</tr>
</tbody>
</table>
<p dir="auto">At idle both ballooned correctly — <code>memory-actual</code> 4297175040 and 4297027584 against a <code>memory-target</code> of 4294967296. <strong>Ballooning at idle is not the differentiator.</strong> Both drivers do it. The difference only appears when the guest touches a page beyond what is backed.</p>
<p dir="auto">Results:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Test</th>
<th>Arm A (Citrix)</th>
<th>Arm B (XCP-ng)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Unattended, idle, 22 hours</td>
<td>4 recreations</td>
<td>0 recreations</td>
</tr>
<tr>
<td>Interactive login</td>
<td>crashed shortly after</td>
<td>survived</td>
</tr>
<tr>
<td>Allocation loop to 14 GiB</td>
<td><strong>domain destroyed in 13 seconds</strong></td>
<td><strong>completed</strong></td>
</tr>
<tr>
<td>Domain IDs over 22 h</td>
<td>137, 139, 140, 141, 151</td>
<td>138, unchanged</td>
</tr>
</tbody>
</table>
<p dir="auto">The allocation loop was a PowerShell script holding 256 MiB chunks and touching every page. Arm A's log file contains its start line and nothing else — not one chunk completed. The host watcher:</p>
<pre><code>07:47:04  PoD=170  TEST-DMC-B=138 TEST-DMC-A=140
07:47:19  PoD=173  TEST-DMC-B=138                  &lt;- arm A gone
07:47:34  PoD=173  TEST-DMC-B=138 TEST-DMC-A=141   &lt;- recreated
</code></pre>
<p dir="auto">Arm B ran the identical script to completion. Windows threw <code>OutOfMemoryException</code> per chunk once it hit its own limit, which is the correct failure — the guest refusing an allocation is right, the hypervisor destroying the domain is not.</p>
<p dir="auto">I then left both running and kept sampling every 15 seconds. Over the following <strong>22 hours</strong>, 5,255 samples:</p>
<ul>
<li><strong>Arm B held a single domain ID (138) throughout. Not one recreation.</strong></li>
<li>Arm A was destroyed and rebuilt four times — domain IDs 137, 139, 140, 141, 151 — with the host's   PoD crash count going 167 to 176.</li>
</ul>
<p dir="auto">Same host, byte-identical memory limits, both idle at a logon prompt. (Domain IDs increment globally, so the gaps in arm A's sequence are other VMs starting, not extra crashes.)</p>
<h2>What I think is worth discussing</h2>
<p dir="auto">I do not think Xen's behaviour is the bug. Xen cannot swap, PoD exhaustion leaves it no option, and an operator who sets <code>static-max</code> at four times <code>dynamic-max</code> has accepted that risk. Fair enough.</p>
<p dir="auto"><strong>What made this take an evening is that nothing anywhere says so.</strong></p>
<ul>
<li>
<p dir="auto"><strong>XO's VM creation form writes <code>memory-dynamic-max</code> and nothing else.</strong> I verified this   separately: cloning a template that carried 4-to-16 and setting the form's RAM field to 8 GiB produced <code>dynamic-min</code> 4 GiB, <code>dynamic-max</code> 8 GiB, <code>static-max</code> 16 GiB. Three of the four values came from the template. The operator types one number and sees one number; the Advanced fields that would reveal the rest are collapsed by default.</p>
<p dir="auto"><strong>This was the XO 5 UI, not XO 6</strong> — see the note below, since it may already be different there.</p>
</li>
<li>
<p dir="auto"><strong>XO reports nothing when a domain is killed this way.</strong> No alert, no task, no message on the VM.</p>
</li>
<li>
<p dir="auto"><strong>With <code>on_crash=Start</code> the domain restarts immediately</strong>, so the guest records only an unclean restart with no bugcheck code — which points the operator at Windows, which is innocent.</p>
</li>
<li>
<p dir="auto"><strong>The cause appears only in <code>xl dmesg</code> on the host</strong>, which is not visible through XO at all.</p>
</li>
</ul>
<p dir="auto">So a supported path through the UI produces a configuration that will destroy the guest, and nothing in the management layer indicates it either at creation or at failure.</p>
<p dir="auto"><strong>A caveat on all of the above: I was using the XO 5 interface throughout.</strong> I have not tried this in XO 6, so if the new VM creation form surfaces all four memory values, or warns when a clone's <code>dynamic-max</code> lands well below the template's <code>static-max</code>, then part of this is already solved and I am reporting a problem you have fixed. Worth someone confirming either way, because the XAPI-level behaviour is the same underneath and the difference would be entirely in what the UI shows.</p>
<p dir="auto">The <code>domain_crash</code> reporting gap is more likely to be common to both, since it is about surfacing a host-level event rather than about a form.</p>
<p dir="auto">Two things that would have saved the evening, in rough order of value:</p>
<ol>
<li>A warning in XO when a VM's <code>static-max</code> materially exceeds its <code>dynamic-max</code> — or simply surfacing all four values where RAM is set, rather than one.</li>
<li>Something visible in XO when a domain is destroyed by <code>domain_crash</code>. Even a task or a VM message would have pointed me at the host log on day one.</li>
</ol>
<p dir="auto">And if the Citrix tools genuinely do not reclaim under PoD on XCP-ng, that seems worth stating plainly in the guest tools documentation. The current guidance recommends XCP-ng tools without naming this as a consequence, and the failure mode looks nothing like a driver problem.</p>
<h2>Environment</h2>
<pre><code>XCP-ng 8.3.0, platform 3.4.0, xapi 26.1.11, build 20260707
Xen 4.17.6-9, changeset 8c80ec836310, pq 9f872f8199c0
Xen Orchestra: XO 5 UI (Community Edition, from sources)
Host: 768 GiB RAM, no memory pressure at any point (710 GiB free during testing)
Guests: Windows Server 2022 Standard, 10.0.20348, UEFI, Secure Boot
</code></pre>
<p dir="auto">Happy to provide the full watcher log, <code>xl dmesg</code> extracts, or the allocation script if useful.</p>
<p dir="auto">Is this known? Is the Citrix-tools reclaim failure expected on XCP-ng, or worth reporting upstream? And does the XO 6 creation form already handle the memory side of this differently?</p>
]]></description><link>https://xcp-ng.org/forum/topic/12399/windows-guests-destroyed-by-pod-exhaustion-with-citrix-tools-xcp-ng-tools-fix-it-but-xo-gives-no-warning-either-way</link><generator>RSS for Node</generator><lastBuildDate>Mon, 03 Aug 2026 11:15:05 GMT</lastBuildDate><atom:link href="https://xcp-ng.org/forum/topic/12399.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 03 Aug 2026 09:17:14 GMT</pubDate><ttl>60</ttl></channel></rss>