Repository navigation
filesystem: test RENAME_EXCHANGE bookkeeping on microVM virtio-fs shares - #493
Merged
Pedro Henrique Penna (ppenna) merged 4 commits intoOct 12, 2026
Merged
Pedro Henrique Penna (ppenna) merged 4 commits into
Pedro Henrique Penna (ppenna) merged 4 commits into
Conversation
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The cross-repository pin and snapshot behavior require final human review across the supported hypervisor platforms.
0 open findings
What changed in this PR
Pins OpenVMM tests and adds end-to-end coverage documenting correct RENAME_EXCHANGE behavior across snapshots.
Changes:
- Promotes OpenVMM’s exchange bookkeeping tests.
- Exercises file and directory exchanges before snapshot capture and after restore.
- Documents Linux and Windows behavior.
| File | Description |
|---|---|
openvmm |
Pins the OpenVMM test revision. |
scripts/nvx_tools/microvm_test_scripts/filesystem-live.sh |
Performs and validates live exchanges. |
scripts/nvx_tools/microvm_tests.py |
Verifies host-side exchange results. |
scripts/test_microvm_tests.py |
Tests platform-specific assertions. |
doc/run.md |
Documents user-visible behavior. |
doc/design/machine-and-device-abi.md |
Records the device contract. |
doc/design/validation.md |
Records validation coverage. |
doc/openvmm-upstream-roadmap.md |
Tracks the promoted revision. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/fix-issue-306-validate-implementation
branch
from
October 12, 2026 19:47
a8ae26d to
bdb8fa8
Compare
Part of #306. Pins OpenVMM a5955855c, the head of nanvix/openvmm#132 and one commit past the current pin, d43dd87d5. The commit adds tests for RENAME_EXCHANGE on microVM virtio-fs shares and changes no OpenVMM code: - Two files, one with a hard link and a handle open across the exchange, and two directories in different parents with nodes below them: each node keeps its own object under exactly its new names, and a snapshot taken right after the exchange records those names and restores them. - An exchange that would push a name below the destination past the alias path limit fails with E2BIG before the host changes anything, which shows that the alias preflight models the exchange. - On Windows hosts, which reject every rename flag with EINVAL, the same tests check that the exchange changes nothing. nanvix/openvmm#117, which dev already pins, made HostFs swap the names of both objects. The Guide's virtio-fs page now also states how each host treats rename flags. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The OpenVMM pin moves to a5955855c, one commit past d43dd87d5. Record the new pin in the roadmap's scope and branch graph, count the 146 commits past the mapped tip, and index the new commit as position 312. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Part of #306. The live stage of the filesystem-snapshot scenario now swaps two files and two directories with renameat2(RENAME_EXCHANGE) right before the guest requests its capture. No lookup runs between the exchanges and the capture, so the capture records exactly the names that OpenVMM tracks after them. The guest holds both files, both directories, and a file in each directory open across the exchanges and the capture. With the share's zero entry lifetimes, the guest kernel forgets any object that nothing holds, and OpenVMM then drops the object's node, so only held objects reach the capture. With the one-way bookkeeping that nanvix/openvmm#117 replaced, the capture fails with "inode has no bounded reopenable aliases". The guest uses util-linux's exch, which the Alpine and Azure Linux guests ship. The Ubuntu guest has no exch, so the script makes the x86-64 system call through Perl instead and reports errno as exch does. After each restore, the guest requires every handle to read its own object and each name to hold the object that the exchanges left there. Linux hosts pass the flag to renameat2, while Windows hosts reject every rename flag with EINVAL before changing anything. The guest accepts either outcome only when both exchanges agree. After the capture, the host requires its platform's outcome on the share (assert_live_exchange): swapped names on Linux and unchanged names on Windows. A unit test covers both layouts and a partial swap. doc/design/validation.md describes the new coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
doc/run.md tells users that, on a Linux host, the guest can swap two names in an rw mapping with renameat2(RENAME_EXCHANGE), as exch does, and that a snapshot captured right after the swap keeps each name with its object, while a Windows host rejects rename flags with EINVAL and changes neither name. doc/design/machine-and-device-abi.md records the same contract for the device. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/fix-issue-306-validate-implementation
branch
from
October 12, 2026 21:35
bdb8fa8 to
3f4739b
Compare
Pedro Henrique Penna (ppenna)
deleted the
agents/fix-issue-306-validate-implementation
branch
October 12, 2026 22:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Fixes #306.
nanvix/openvmm#117, which
devalready pins, made OpenVMM's virtio-fs server swap the names that it tracks for both objects of aRENAME_EXCHANGE, in its bookkeeping and in its alias-limit preflight. That is the first option in #306. The work that remained was the tests that prove it and a pin that carries them. This PR pins those OpenVMM tests (nanvix/openvmm#132), adds an end-to-end check in which a real guest exchanges names right before a snapshot, and documents the behavior.Why
For each FUSE node, the microVM virtio-fs server keeps every name that the guest has used for the node's object, and operations on the node use one of them. HostFs used to treat every rename as a one-way move. After an exchange, the node of the object that left the destination had no names left, and its path named the other object. Until the guest looked that name up again, operations on the node reached the other object, and a capture failed with
inode has no bounded reopenable aliases. No test checked that an exchange keeps each node on its own object, or that a snapshot taken right after an exchange saves and restores.Changes
6d2712ac4a5955855c, the head of nanvix/openvmm#132 and one commit pastd43dd87d5, whichdevpins. It changes only the gitlink, and the OpenVMM commit changes only tests and the Guide. The newvirtiofstests exchange two files, one hard-linked and one open across the exchange, and two directories in different parents with nodes below them. They check each node's exact names, the path that its operations use, the object that it reaches, and a save and restore right after the exchange. They also check that an exchange that would push a name below the destination past the alias path limit fails withE2BIGbefore the host changes anything. On Windows, where the host rejects rename flags withEINVAL, the same tests require the exchange to change nothing.5d195406cdoc/openvmm-upstream-roadmap.mdrecords the new pin and indexes its commit as position 312.ddc69322etest-microvm'sfilesystem-snapshotscenario, the guest exchanges two files and two directories withrenameat2(RENAME_EXCHANGE)right before the capture. It holds all four open, along with a file in each directory, because the share's zero entry lifetimes make the guest forget, and OpenVMM drop, any object that nothing holds. The guest uses util-linux'sexchon Alpine and Azure Linux; Ubuntu has noexch, so the guest makes the x86-64 system call through Perl. After each restore, every handle must read its own object, and each name must hold the object that the exchange left there. After the capture, the host requires swapped names on Linux and unchanged names on Windows (assert_live_exchange, which a new unit test covers).3f4739bcadoc/run.mdanddoc/design/machine-and-device-abi.mddescribeRENAME_EXCHANGEon microVM shares.Acceptance criteria
RENAME_EXCHANGE, each node either resolves to its own object at its new path, or the exchange is rejected without any host change. Linux hosts exchange the names, and every node follows its object: the unit tests check each node's names and object, and in the scenario every handle reads its own object after restore. Windows hosts reject the exchange withEINVALbefore changing anything: the unit tests check every node and the host tree, and the scenario checks the share.Behavior and compatibility
d43dd87d5, whichdevpins, because its commit adds only a test module and a Guide row.RENAME_WHITEOUTneeds no special handling. It moves the object as a plain rename does and leaves a new whiteout object at the source, which no node can refer to yet, so the one-way bookkeeping is correct for it.OpenVMM promotion
mainatd43dd87d5, whichdevalready pins. It has one commit and no other prerequisites. The OpenVMM fork runs no CI on pull requests, so this PR's CI also covers it:test-openvmm-unitruns the whole workspace, including the new tests, on Linux and Windows.a5955855c1b35af830ede983c8857dc5a781f977, the same commit as that PR's head (tree87bb04d64115d0adf542f1bbd0797bce01b08fba), with a good SSH signature from ppenna@microsoft.com.a5955855ccarries the patch that this PR pinned earlier asa28d4a5f8and02cb4737d, rebased ontomainatd43dd87d5.git range-diffpairs it with each of them as identical, and their diffs against their bases are byte-identical. This is patch equivalence: the trees also differ by themaincommits in between.70dde4c65keeps the partition halt state across snapshots, and9b2073ded..d43dd87d5carry VM time across snapshots, including invmcore, whichvirtiofsbuilds on. All the validation below was therefore re-run ata5955855c.6d2712ac4, whose only parent isdevat904601681.Validation
All results below are for this head,
3f4739bca, with OpenVMMa5955855c.Run locally on Windows:
python scripts\nvx.py verify, ruff (check and format), pyright (Linux and Windows), and shellcheck and shfmt on the guest scripts thatcheck-qualitylints and on the changed guest script.validate-nvxunit tests: 972 passed (108 skipped).virtiofs:cargo clippy --all-targetsandcargo doc --no-depsare clean,cargo nextest run --profile agentpasses 109 tests, andcargo xtask fmt --fixmakes no changes.On bare-metal hosts, with OpenVMM built from
a5955855cand the guest artifacts ofv0.1.0-dev.b1dadb73b4e7, whose guest inputs this head does not change:virtiofsnextest: 117 passed, 1 skipped. With OpenVMM built on the host,filesystem-snapshotpasses with the Alpine, Ubuntu, and Azure Linux guests.filesystem-snapshotpasses with the Alpine, Ubuntu, and Azure Linux guests.filesystem-snapshotpasses with the Alpine, Ubuntu, and Azure Linux guests. The guest's exchanges fail withInvalid argumentand change nothing.Mutation checks on prometheus30, at this head, show that the new checks catch the old one-way bookkeeping:
virtiofsunit tests: with the old bookkeeping, both new exchange tests and the existing policy test fail. With an alias preflight that treats an exchange as a one-way move, only the new limit test fails; no earlier test covered that path.filesystem-snapshot: an OpenVMM built with the old bookkeeping fails the live capture withsave failed: {virtiofs-…: inode has no bounded reopenable aliases}.The NVX CI covers KVM, MSHV, and WHP, including
filesystem-snapshotwith the Alpine and Ubuntu guests.