Repository navigation
nvx-rs: compute the outermost export paths with one function - #606
Merged
Pedro Henrique Penna (ppenna) merged 1 commit intoOct 19, 2026
Merged
Conversation
filesystem::plan reduces three lists of canonical host paths to the paths that no other path in the list contains, and did it three ways. export_roots sorted, deduplicated, and filtered the mapped paths inline. denied_paths sorted and deduplicated the denied paths, collected the nested ones, and removed them with retain. The paths to which OpenVMM limits a read-only child's writes went through outermost, which filtered Mapped entries by their canonical paths, and plan then mapped and sorted the survivors. outermost now takes the paths themselves: it sorts them, drops duplicates, and returns those that no other contains. export_roots, denied_paths, and the write list of plan call it, and the two inline copies are gone. plan collects a child's read-write mappings as their canonical paths, which is all that the writable flag and the write list need. Each list keeps its contents and order. export_roots and denied_paths ran the same sort, deduplication, and containment test that outermost runs now. plan keeps one mapped entry per canonical path, so deduplicating the read-write paths removes nothing, and sorting them before the containment test instead of after it gives the same sorted list. The plan tests cover the three lists, and a new unit test pins the order, deduplication, and containment by whole components that they share. A throwaway differential test compared the three former computations with outermost on 7.3 million lists of paths, every list of up to three paths and random lists of up to twelve, in Windows and Linux path forms: all results were identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused refactor preserves path-selection semantics, and no blocking issues were identified.
No open issues 🎉
What changed in this PR
Consolidates NVX host filesystem path reduction into one private helper while preserving export, deny, and write-list behavior.
Changes:
- Reuses
outermostto sort, deduplicate, and remove nested paths across all three lists. - Collects read-write mappings directly as canonical paths.
- Adds a unit test covering ordering, duplicates, and whole-component containment.
| File | Description |
|---|---|
nvx-rs/src/host/filesystem.rs |
Centralizes path reduction and tests the shared behavior. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
deleted the
nvx-rs-quality/outermost-paths
branch
October 19, 2026 17:00
This was referenced Oct 19, 2026
Jay (jay23606)
pushed a commit
to jay23606/nvx
that referenced
this pull request
Oct 19, 2026
A failure of restore-time repair is a fatal time-ABI event: it has the repair source and the restore phase, and it stops the VM with the repair power-off status unless the tools run report-only. commands::repair_failed passed those three to Runtime::fail_fatal, and daemon.rs spelled them out again at six sites, each with G_REPAIR_SUPPRESSION. restore_work also inlined the body of release_suppression. No unit test reached any of them, because Runtime::emit_event opened /dev/kmsg and /dev/console itself, so microsoft#605, microsoft#606, and microsoft#607 left this refactor until a test seam existed. Runtime::repair_failure, beside Runtime::conformance_failure, now passes the repair status, source, and phase. repair_failed and the six daemon sites call it, and restore_work calls release_suppression. Two new PrivilegedOps methods, write_kernel_log and write_console, are the seam. RealOps runs the code with which emit_event wrote an event's kernel log record and console line, and the FakeOps of the unit tests records their bytes, as it already records port writes and power-off requests. Behavior is unchanged. Every repair failure passes the status, code, source, phase, and detail that it passed before. An event writes the same bytes, with the same open flags, to the kernel log, port B, and the console, in that order, and reads the asynchronous-output flag at the same points. A new unit test checks a repair failure's event line at all three destinations and its power-off status, with and without report-only mode, in the glibc and musl test runs. The microVM restore scenarios run restore_work, and so release_suppression, in guests on KVM, MSHV, and WHP. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Oct 19, 2026
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.
Summary
planinnvx-rs/src/host/filesystem.rsreduces three lists of canonical host paths to the paths that no other path in the list contains: the export roots, the denied paths, and the paths to which OpenVMM limits a read-only child's writes. It did that three ways:dedup, and filter inexport_roots;dedup, nested list, andretainindenied_paths;outermost, which filteredMappedentries by their canonical paths, followed by a map and a sort inplan.This change gives the module one
outermost(Vec<PathBuf>) -> Vec<PathBuf>, which sorts the paths, drops duplicates, and keeps those that no other contains. All three lists use it. The rule that decides which paths OpenVMM exports, hides, and lets the guest write now lives in one place, so the three lists cannot drift apart.This is the third
nvx-rs-quality/run. #603 and #605, both merged, had approving Copilot reviews and no feedback to follow. They changedprotocol/exec.rsandguest/managed_agent/exec.rs. This run surveyed the rest of the crate, by reading and with a throwaway duplicate-window script, and skipped every file that an open pull request todevchanged when it started: #585, #596, #597, #598, and #605. It pickedhost/filesystem.rs, which no recent run touched and existing tests cover.The survey's strongest production candidate was the six identical
fail_fatalcalls inguest/time/daemon.rs. As #605 noted, no unit test can reach that code without a seam over the event log and console, so the conservative choice was to leave it as a follow-up.Changes
All changes are in
nvx-rs/src/host/filesystem.rs: 25 insertions and 39 deletions. No public item, message, serde form, fixture, or other file changes.outermostnow takes and returns paths: it sorts them, drops duplicates, and returns those that no other contains. Three sites now share it:export_roots, for the canonical mapped paths, which become the children of the aggregate export;denied_paths, for the denied paths that exist;plan, for the read-write mappings of a read-only child, which become itswritelist.plancollects a child's read-write mappings as their canonical paths instead of&Mappedentries, since thewritableflag and thewritelist need only those.outermost_paths_are_sorted_once_without_the_paths_inside_others, pins the shared behavior that theplantests do not reach directly: nested and repeated paths, and containment by whole components (/a/bkeeps/a/bc).Behavior
export_rootsanddenied_pathsran the same sort,dedup, and containment test (other != path && path.starts_with(other)) thatoutermostnow runs, so their results are unchanged.denied_pathsremoved the nested paths withretaininstead of a filter, but afterdedupboth keep exactly the paths that no other contains, in sorted order.plankeeps oneMappedentry per canonical path, so deduplicating the read-write paths removes nothing. Sorting before the containment test instead of after it yields the same sortedwritelist.Every message,
ErrorKind, check order, limit, OpenVMM argument, and recordedExportPlanis unchanged. The only difference is internal:plannow clones the read-write paths of every child that has any, where it cloned only the outermost ones of a read-only child.I wrote a throwaway differential test, which is not committed. It compiled the three former computations beside the new
outermostand compared their results as raw path strings, so spellings that compare equal had to match too. It ran on two sets of lists:The paths included Windows drive, verbatim, and root forms, and Linux
/,//, and..forms. All 7,322,525 cases were identical.Follow-ups
These turned up in the survey; this change leaves them alone.
guest/time/daemon.rsrepeatsruntime.fail_fatal(PowerOffStatus::Repair, ViolationCode::RepairSuppression, EventSource::Repair, Phase::Restore, ...)six times, andrestore_workinlines the body ofrelease_suppression.commands::repair_failedwraps the same status, source, and phase. ARuntime::repair_failurebesideRuntime::conformance_failurecould serve all of them, once a test seam overRuntime::emit_eventlets a unit test reach them.host/instance.rs,Instance::runtimeandInstance::launchread a JSON record and refuse anotherSTATE_FORMATin two shapes. A private generic reader could serve both while keeping their messages.guest/sys/socket.rs,connect_datagramandUdpSocket::ipv4create the sameSOCK_CLOEXECIPv4 datagram socket.guest/device_io.rs,run_fileandrun_networkdestructure aMeasurement, format it withresult_line, and write it with the sameCommandError::Outputmapping; one helper could serve both.LoopbackSystemforwarding that nvx-rs: track open workload output pipes by their Option alone #605 lists remain.I found no suspected bug in the code that this change touches.
Validation
BASE:
f4b4b8d3f884897952d336f61bc830a11599bf76, which wasorigin/devwhen the run started: the merge of nvx-rs: decode the EXEC header once for both payload decoders #603. Before this pull request was opened,origin/devhad advanced only by the merge of nvx-rs: track open workload output pipes by their Option alone #605 and a performance-baseline update, neither of which changesnvx-rs/src/host/filesystem.rs, and no open pull request todevchanged it.TREE:
450381979ff474189789371b73f45166ecaafced, the tree of this commit. Every host applied the patch to BASE and checked thatgit write-treeequals TREE.Release on every host:
v0.1.0-dev.e8ff3343bcc8. BASE has no release yet, sodownloadtook the one from two first-parent commits earlier. Its OpenVMM,5ab8a84621524f1777b2cb5e65a70dab42c8b453, is the pinned revision.Guest artifacts were rebuilt from TREE on prometheus30, with these steps:
build-guest-binaries --output;test-guest-binaries --binaries, where 34 tests passed;build-initramfswithNVX_GUEST_BINARIES.initramfs.cpio.gz(SHA-256b71e6fb868575c71d733f819d877b63ca426fbb7cf64894d88f81727172f6125), its packages manifest, and its provenance went to the other two hosts, where the SHA-256 digests matched.Local checks on Windows with Rust 1.95.0:
-D warnings, for all targets and features and for the library without default features;cargo testwith all features (262 library tests, 6 fake-OpenVMM tests, and 1 doctest) and with the default features (259 and 1);-D warnings;aarch64-apple-darwin) checks, for bothnvx-rsandaci_edge_sandboxes;test-aci-edge-sandboxestest-microvm, default suitecheck-guest-binaries(277 + 34 musl tests), 493 library tests with all features, artifact bundling, agent bundling, and the Linux half of the differential test; the macOS checks ran locallyOn prometheus32, the suite's time-ABI evidence line counted 1 of 58 boot checks over KVM's CPU-time budget. The suite reports that count but never gates on it, and this change does not touch the guest's time code.
Left to CI:
test-openvmm-unitandtest-openvmm;smp-lapic,managed-exec-config, andsandbox-lifecycle;