Skip to content

filesystem: test RENAME_EXCHANGE bookkeeping on microVM virtio-fs shares - #493

Merged
Pedro Henrique Penna (ppenna) merged 4 commits into
devfrom
agents/fix-issue-306-validate-implementation
Oct 12, 2026
Merged

Pedro Henrique Penna (ppenna) merged 4 commits into
devfrom
agents/fix-issue-306-validate-implementation

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #306.

nanvix/openvmm#117, which dev already pins, made OpenVMM's virtio-fs server swap the names that it tracks for both objects of a RENAME_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

Commit Change
6d2712ac4 Pins OpenVMM a5955855c, the head of nanvix/openvmm#132 and one commit past d43dd87d5, which dev pins. It changes only the gitlink, and the OpenVMM commit changes only tests and the Guide. The new virtiofs tests 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 with E2BIG before the host changes anything. On Windows, where the host rejects rename flags with EINVAL, the same tests require the exchange to change nothing.
5d195406c doc/openvmm-upstream-roadmap.md records the new pin and indexes its commit as position 312.
ddc69322e In the live stage of test-microvm's filesystem-snapshot scenario, the guest exchanges two files and two directories with renameat2(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's exch on Alpine and Azure Linux; Ubuntu has no exch, 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).
3f4739bca doc/run.md and doc/design/machine-and-device-abi.md describe RENAME_EXCHANGE on microVM shares.

Acceptance criteria

  • After 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 with EINVAL before changing anything: the unit tests check every node and the host tree, and the scenario checks the share.
  • A snapshot taken right after an exchange saves and restores, or the exchange is rejected. The unit tests save and restore right after the exchange, and the scenario captures right after it and restores twice.

Behavior and compatibility

  • Neither OpenVMM nor NVX changes at run time: the behavior shipped with virtiofs: add a per-subtree access policy to microVM shares nanvix/openvmm#117. The new pin builds the same OpenVMM release binary sources as d43dd87d5, which dev pins, because its commit adds only a test module and a Guide row.
  • RENAME_WHITEOUT needs 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.
  • Guest requests to a microVM share cannot race the bookkeeping of an exchange: the profile has one request queue, whose worker handles one request at a time.

OpenVMM promotion

  • Source: virtiofs: test RENAME_EXCHANGE node names and snapshots nanvix/openvmm#132, open and ready for review, based on main at d43dd87d5, which dev already 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-unit runs the whole workspace, including the new tests, on Linux and Windows.
  • Pinned revision: a5955855c1b35af830ede983c8857dc5a781f977, the same commit as that PR's head (tree 87bb04d64115d0adf542f1bbd0797bce01b08fba), with a good SSH signature from ppenna@microsoft.com.
  • Rebase: a5955855c carries the patch that this PR pinned earlier as a28d4a5f8 and 02cb4737d, rebased onto main at d43dd87d5. git range-diff pairs 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 the main commits in between. 70dde4c65 keeps the partition halt state across snapshots, and 9b2073ded..d43dd87d5 carry VM time across snapshots, including in vmcore, which virtiofs builds on. All the validation below was therefore re-run at a5955855c.
  • Pin commit: the gitlink-only commit 6d2712ac4, whose only parent is dev at 904601681.
  • Merge order: merge virtiofs: test RENAME_EXCHANGE node names and snapshots nanvix/openvmm#132 first. Re-pin if the merge rewrites the commit.

Validation

All results below are for this head, 3f4739bca, with OpenVMM a5955855c.

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 that check-quality lints and on the changed guest script.
  • validate-nvx unit tests: 972 passed (108 skipped).
  • OpenVMM virtiofs: cargo clippy --all-targets and cargo doc --no-deps are clean, cargo nextest run --profile agent passes 109 tests, and cargo xtask fmt --fix makes no changes.

On bare-metal hosts, with OpenVMM built from a5955855c and the guest artifacts of v0.1.0-dev.b1dadb73b4e7, whose guest inputs this head does not change:

Host Platform Results
prometheus30 Linux/MSHV (Azure Linux 3.0, Linux 6.6) OpenVMM virtiofs nextest: 117 passed, 1 skipped. With OpenVMM built on the host, filesystem-snapshot passes with the Alpine, Ubuntu, and Azure Linux guests.
prometheus32 Linux/KVM (Ubuntu, Linux 7.0) With prometheus30's OpenVMM, filesystem-snapshot passes with the Alpine, Ubuntu, and Azure Linux guests.
prometheus28 Windows/WHP (HPE ProLiant DL380 Gen10) With OpenVMM built on the host, filesystem-snapshot passes with the Alpine, Ubuntu, and Azure Linux guests. The guest's exchanges fail with Invalid argument and change nothing.

Mutation checks on prometheus30, at this head, show that the new checks catch the old one-way bookkeeping:

  • virtiofs unit 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 with save failed: {virtiofs-…: inode has no bounded reopenable aliases}.

The NVX CI covers KVM, MSHV, and WHP, including filesystem-snapshot with the Alpine and Ubuntu guests.

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.

🔵 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.

@ppenna
Pedro Henrique Penna (ppenna) force-pushed the agents/fix-issue-306-validate-implementation branch from a8ae26d to bdb8fa8 Compare October 12, 2026 19:47
Copilot AI balanced review requested due to automatic review settings October 12, 2026 19:47

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.

🟡 Changes recommended

The PR description and validation evidence reference an obsolete OpenVMM revision rather than the pinned exact head.

1 open finding

🧠 Review effort: Balanced

Comment thread doc/openvmm-upstream-roadmap.md Resolved
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>
Copilot AI balanced review requested due to automatic review settings October 12, 2026 21:35
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the agents/fix-issue-306-validate-implementation branch from bdb8fa8 to 3f4739b Compare October 12, 2026 21:35

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.

🟡 Changes recommended

The PR description and validation evidence reference an obsolete OpenVMM pin and NVX head rather than the revisions currently being merged.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced

Comment thread doc/openvmm-upstream-roadmap.md Resolved
@ppenna
Pedro Henrique Penna (ppenna) merged commit a3f320c into dev Oct 12, 2026
32 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the agents/fix-issue-306-validate-implementation branch October 12, 2026 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sandbox: fix RENAME_EXCHANGE alias bookkeeping on microVM virtio-fs shares

2 participants