Skip to content

Draft: add manual VHDX compaction command for stopped WSL distros - #40481

Merged
Ben Hillis (benhillis) merged 38 commits into
microsoft:masterfrom
Guayamose:draft/vhdx-compact-manual-command
Aug 12, 2026
Merged

Ben Hillis (benhillis) merged 38 commits into
microsoft:masterfrom
Guayamose:draft/vhdx-compact-manual-command

Conversation

@Guayamose

@Guayamose Rafa Pradillo (Guayamose) commented May 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary of the Pull Request

Related to #40243 and #4699.

This is an exploratory draft PR for a manual-only VHDX compaction path.

It adds a new manual command:

  • wsl --manage <Distro> --compact

The command compacts the VHDX backing file for a stopped WSL 2 distro using the Windows Virtual Disk API.

This PR intentionally does not add automatic compaction yet.

PR Checklist

Detailed Description of the Pull Request / Additional comments

Scope

Included:

  • Adds an internal VHD compaction helper using OpenVirtualDisk and CompactVirtualDisk.
  • Adds service/client plumbing for compacting a distro VHD.
  • Adds wsl --manage <Distro> --compact.
  • Rejects running distros / in-use VHDs.
  • Preserves clear error behavior for ERROR_SHARING_VIOLATION.
  • Adds tests for the manual command path.
  • Updates help/localization strings.

Not included:

  • No automatic compaction.
  • No shutdown hook.
  • No .wslconfig policy.
  • No threshold/cooldown logic.
  • No deferred retry/background task.
  • No Docker-specific special casing.
  • No special handling for Docker-managed VHDs.

Motivation

The broader issue in #4699 is that WSL 2 distro VHDX files can grow significantly and not release space back to the host automatically.

In #40243 I proposed a safer path around shutdown/offline compaction. Before attempting any automatic policy, this PR adds a smaller manual command first, so the Virtual Disk API integration and safety model can be reviewed independently.

Validation

Built successfully on Windows:

  • cmake .
  • cmake --build . --config Debug --target wsl wslservice wsltests -- /m
  • cmake --build . --config Debug --target msixinstallerpackage -- /m

Tested:

  • UnitTests::UnitTests::Compact passed.
  • Manual compact against a stopped disposable Ubuntu WSL 2 distro succeeded.
  • The distro booted successfully after compaction.
  • Running distro case rejected as expected with Wsl/Service/WSL_E_DISTRO_NOT_STOPPED.
  • wsl --manage Ubuntu --compact --resize 10GB did not compact and failed argument validation/help as expected.

Manual validation result:

  • Command: wsl --manage Ubuntu --compact
  • Output: La operación se completó correctamente.
  • Exit code: 0
  • VHD delta: -2,097,152 bytes
  • Boot check command: wsl -d Ubuntu -- echo ok
  • Boot check output: ok
  • Boot check exit code: 0

Running distro validation:

  • Command: wsl --manage Ubuntu --compact
  • Error: Wsl/Service/WSL_E_DISTRO_NOT_STOPPED
  • Exit code: -1
  • VHD delta: 0

Notes

This is opened as a draft because the intended first step is design and maintainer feedback on the manual command surface and service/helper integration.

Open questions:

  • Is wsl --manage <Distro> --compact the right CLI surface?
  • Should this remain manual first before any automatic policy is considered?
  • Should the helper report before/after size or keep output minimal?
  • Should fixed/non-compactable VHDs get a more specific message?
  • Are there preferred telemetry/logging patterns for this operation?

Future work, if this direction is acceptable:

  • opt-in shutdown-triggered policy
  • threshold/cooldown
  • deferred retry/backoff
  • richer telemetry/logging
  • reclaim estimation

@Guayamose
Rafa Pradillo (Guayamose) requested a review from a team as a code owner May 10, 2026 02:44
Copilot AI lite review requested due to automatic review settings May 10, 2026 02:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a manual-only VHDX compaction path for stopped WSL 2 distributions, exposed via wsl --manage <Distro> --compact, with service plumbing and a Virtual Disk API helper.

Changes:

  • Introduces --compact in wsl.exe --manage, routed through SvcComm to the service.
  • Implements a service-side CompactDistribution path that rejects non-WSL2 and running/in-use distros and invokes CompactVirtualDisk.
  • Updates help/localization text and adds a WSL2 unit test covering the compact flow.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/windows/UnitTests.cpp Adds help text expectation and a new WSL2 test for --manage --compact.
src/windows/service/inc/wslservice.idl Extends ILxssUserSession with CompactDistribution RPC method.
src/windows/service/exe/LxssUserSession.h Declares CompactDistribution on the COM class + impl.
src/windows/service/exe/LxssUserSession.cpp Implements CompactDistribution validation and VHD compaction call path.
src/windows/inc/wsl.h Adds --compact manage option constant.
src/windows/common/WslCoreFilesystem.h Declares CompactVhd helper.
src/windows/common/WslCoreFilesystem.cpp Implements CompactVhd via OpenVirtualDisk + CompactVirtualDisk.
src/windows/common/WslClient.cpp Adds CLI parsing/dispatch for --manage --compact.
src/windows/common/svccomm.hpp Adds SvcComm::CompactDistribution declaration.
src/windows/common/svccomm.cpp Wires SvcComm::CompactDistribution to ILxssUserSession.
localization/strings/en-US/Resources.resw Adds --compact help text + locked token list update.
localization/strings/es-ES/Resources.resw Adds Spanish --compact help text + locked token list update.

Comment thread src/windows/service/inc/wslservice.idl
Comment thread src/windows/common/WslClient.cpp
@Guayamose

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

@Guayamose
Rafa Pradillo (Guayamose) marked this pull request as draft May 10, 2026 03:30
@Guayamose
Rafa Pradillo (Guayamose) marked this pull request as ready for review May 10, 2026 11:43
Copilot AI review requested due to automatic review settings May 10, 2026 11:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread localization/strings/en-US/Resources.resw

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.

Comment thread src/windows/service/exe/LxssUserSession.cpp Outdated
Comment thread test/windows/UnitTests.cpp Outdated
Comment thread test/windows/UnitTests.cpp Outdated
@Guayamose
Rafa Pradillo (Guayamose) marked this pull request as draft May 10, 2026 12:44
@Guayamose
Rafa Pradillo (Guayamose) marked this pull request as ready for review May 10, 2026 12:46
Copilot AI review requested due to automatic review settings May 10, 2026 12:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings May 12, 2026 02:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 33 out of 33 changed files in this pull request and generated no new comments.

Comment thread src/windows/service/exe/LxssUserSession.cpp Outdated
Comment thread localization/strings/cs-CZ/Resources.resw Outdated
Comment thread src/windows/service/inc/wslservice.idl Outdated
Copilot AI review requested due to automatic review settings May 13, 2026 01:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 16 changed files in this pull request and generated 4 comments.

Comment thread src/windows/service/inc/wslservice.idl
Comment thread src/windows/service/exe/LxssUserSession.cpp
Comment thread localization/strings/en-US/Resources.resw Outdated
Comment thread src/windows/common/WslClient.cpp
Copilot AI review requested due to automatic review settings May 13, 2026 02:15
Copilot AI review requested due to automatic review settings August 10, 2026 17:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@OneBlue

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI review requested due to automatic review settings August 10, 2026 22:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings August 10, 2026 22:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Guayamose

Copy link
Copy Markdown
Contributor Author

Blue (@OneBlue) Formatting is fixed. Could you run "/azp run" again please?

@OneBlue

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI review requested due to automatic review settings August 11, 2026 08:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Guayamose

Copy link
Copy Markdown
Contributor Author

Blue (@OneBlue) Sorry again, It should pass now.

@OneBlue

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@Guayamose

Copy link
Copy Markdown
Contributor Author

Blue (@OneBlue) Sorry for the repeated pings. WSLC failed; it may be flaky or an interaction with the recent WSLC changes in master. I can’t access the detailed result could you check it?

@OneBlue Blue (OneBlue) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Test failure was a known issue that's unrelated to this change

@benhillis

Copy link
Copy Markdown
Member

Thanks again for your patience here, I'm going to go ahead and merge. Nice job.

@benhillis
Ben Hillis (benhillis) merged commit 51541ce into microsoft:master Aug 12, 2026
9 checks passed
seathatflowsinourveins (seathatflowsinourveins) added a commit to seathatflowsinourveins/native-agent-stack that referenced this pull request Oct 6, 2026
…n tools; reclaim WSL VHDX with wsl --manage --compact (#753)

### Scope

One anti-pattern log row in `docs/harness-defaults.md`, following the user's 2026-10-05 request to resolve the core reasons for NativeStack's disk growth. Lane: foundation.

The row's facts:
- NativeStack's root fell to 191 GB free, and its VHDX on Z: grew to 1,065 GB for 765 GB used.
- The bulk was finished work: 403 worktrees, 124 GB of `/var/tmp` build scratch from a session that had ended, 56.5 GB of 1,802 byte-identical fixture-binary copies, 27.8 GB of per-session index databases, about 75 GB of superseded gateway builds, and 30 GB of unused images.
- The cleanup reached 529 GB free, with every uncommitted change and the one local-only gateway patch preserved first.

The rule closes each job with each tool's own command. It reclaims VHDX space with WSL 3.0.1's native `wsl --manage <distro> --compact`, and leaves sparse VHD off while WSL refuses it without `--allow-unsafe`.

### SOTA sources

- [git-worktree](https://git-scm.com/docs/git-worktree): `remove` refuses unclean worktrees without `--force`.
- [uv `cache prune`](https://docs.astral.sh/uv/reference/cli/#uv-cache-prune) and [docker `image prune`](https://docs.docker.com/reference/cli/docker/image/prune/).
- microsoft/WSL:
  - [PR #40481](microsoft/WSL#40481): `--compact` force-terminates the target distro and runs an offline `e2fsck -E discard` before `CompactVirtualDisk`;
  - tag 3.0.1, `src/windows/service/exe/LxssUserSession.cpp:1761-1921`, where `--set-sparse true` is refused without `--allow-unsafe`;
  - [PR #41726](microsoft/WSL#41726): lifts that refusal in tag 3.0.2 and marks sparse experimental.

### Evidence-class table

| Claim | Evidence class | Source |
| --- | --- | --- |
| Sizes and counts | host measurement on NativeStack (`du`, `df`, `git worktree list`) | the coordinator's private actions log |
| WSL compact and sparse behaviour | upstream source review at tag 3.0.1, plus PRs | the links above |
| git, uv and docker commands | upstream docs | the links above |

### Local commands run

- `uv run --no-project --with pyyaml python -m unittest` over the 416 tests that reference `harness-defaults.md`: OK (2 skipped).
- `python3 scripts/validate.py`: exit 0, after the registry-last commit.
- `python3 scripts/validate_convergence.py --all-recorded`: exit 0.
- The login-name scan is clean.

### Decision record

None new; the anti-pattern log row is the record.

### Host evidence

Sanitized counts only. No host paths or user names.

### Checklist

- [x] No GitHub Actions or workflows changed.
- [x] No secrets printed, logged or committed.
- [x] No paid hosting or billing surface.
- [x] Peer-owned untracked files and worktrees preserved. Each peer pruned its own data; the coordinator removed only data from ended sessions and its own lane, by literal target.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants