Repository navigation
nvx-rs: read a GPT disk's table through the guest's block device - #771
Merged
Merged
Conversation
"p1" was shorthand that each reader had to decode. Name the partition explicitly in nvx::gpt's API, errors, and documentation: `Disk::p1` and `Disk::read_p1` become `Disk::first_partition` and `Disk::read_first_partition`, and `GptError::P1TooLarge` becomes `GptError::FirstPartitionTooLarge`. Tests and comments name the other partitions by their numbers. Nothing else in the repository calls these yet. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1b4b569c-a481-43aa-bfd8-c14a9762c371
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The seek-based size query can disrupt concurrent readers and leave the shared file offset at EOF.
1 open issue
What changed in this PR
Adds guest-side GPT table reading through a Linux block device, reusing the existing strict GPT validator as an incremental step toward layered-root support. Kernel partition comparison remains deferred to #770.
Changes:
- Adds
guest::gpt::read_disk, device geometry discovery, and typed errors. - Renames first-partition APIs and updates their tests.
- Documents the new module and its scope.
| File | Description |
|---|---|
nvx-rs/src/lib.rs |
Lists guest GPT support in crate documentation. |
nvx-rs/src/guest/sys/mod.rs |
Re-exports the logical block-size wrapper. |
nvx-rs/src/guest/sys/ioctl.rs |
Adds BLKSSZGET support and tests. |
nvx-rs/src/guest/mod.rs |
Exposes and documents the GPT module. |
nvx-rs/src/guest/gpt.rs |
Implements device-backed table reading, errors, and tests. |
nvx-rs/src/gpt/tests.rs |
Updates tests for renamed first-partition APIs. |
nvx-rs/src/gpt/mod.rs |
Renames first-partition methods and documentation. |
nvx-rs/src/gpt/error.rs |
Renames the first-partition size error. |
nvx-rs/README.md |
Documents the new module and renamed APIs. |
doc/project-structure.md |
Lists shared and guest GPT functionality. |
Review effort: Balanced
A guest that boots from a GPT disk needs the disk's table, whose disk GUID a boot parameter names, from the block device that the kernel attached. nvx::gpt reads a table through any source at a geometry that its caller states, so the guest only has to supply the device's. Add nvx::guest::gpt::read_disk, which asks a block device that the caller opened for its logical block size and its size, with BLKSSZGET and BLKGETSIZE64, as blockdev does, and reads and checks the table there with Disk::read and the caller's Expected values. It only reads the device, at explicit offsets, so it never moves the file's position and callers may share the file. It neither compares the partitions that the kernel created with the table nor asks the kernel to reread it; a disk that the host stages read-only does not change under the guest. The two ioctl wrappers live in guest::sys beside BLKFLSBUF. They borrow the caller's descriptor, which they neither read nor write. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1b4b569c-a481-43aa-bfd8-c14a9762c371
Enrique Saurez (esaurez)
force-pushed
the
esaurez/a3-gpt-disk-guid-20261022
branch
from
October 22, 2026 21:24
bee76fb to
934b0aa
Compare
Enrique Saurez (esaurez)
marked this pull request as ready for review
October 22, 2026 21:29
Enrique Saurez (esaurez)
deleted the
esaurez/a3-gpt-disk-guid-20261022
branch
October 22, 2026 22:10
1 task
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.

Adds
nvx::guest::gpt::read_disk, which reads the partition table of a GPT disk through the block device that the guest's kernel attached, and checks it, with the expected disk GUID, throughnvx::gpt(#673). The kernel keeps no disk GUID, so a guest that must check the one that a boot parameter names reads it from the table, whose header CRC covers it. The partitions that the guest then uses, such as/dev/vda2, are the ones that the kernel created when it found the disk.This is the first, smaller iteration of A3.3's device code. #715 also compared the kernel's partitions with the table, reread the table when they differed, and tested all of it in a microVM. That guards against a table that changes under a running kernel, which a disk that the host stages read-only and attaches when it creates the VM never does, so #770 tracks it, with #715 as its reference.
What changed
nvx::guest::gpt::read_disk(&File, &Expected) -> Result<Disk, DeviceError>asks the device for its logical block size and its size, withBLKSSZGETandBLKGETSIZE64, asblockdev --getssand--getsize64do, and reads and checks the table there withDisk::read. It only reads, at explicit offsets, so a read-only descriptor will do, and it never moves the file's position, so threads may share the file.DeviceErrorsays whether the block size, the size, or the table failed; a file that is not a block device fails at its block size, withENOTTY.nvx::guest::syswrapsBLKSSZGETandBLKGETSIZE64besideBLKFLSBUF. The wrappers borrow the caller's descriptor, which they neither read nor write.nvx::gpt'sDisk::p1,Disk::read_p1, andGptError::P1TooLarge, from nvx-rs: add a strict GPT reader for layered root disks #673, becomeDisk::first_partition,Disk::read_first_partition, andGptError::FirstPartitionTooLarge, so that no name or document uses the shorthand "p1". Nothing else calls them yet.doc/project-structure.mdlist the module, and the project structure now listsnvx::gpttoo.Part of #621. Refs #622, #770.
Validation
This head, 934b0aa, is on
devat ed6a603.devhas since merged #743 and #672, which change none of this pull request's files, and innvx-rsonly its host side, from which the guest binaries are not built.On Windows 11 (MSVC, Rust 1.95.0) and on an Azure Linux 3.0 virtual machine as a non-root user (Rust 1.95.0), in
nvx-rswithNVX_BUNDLE=skip:cargo fmt --all --checkcargo clippy --locked --all-targets --all-features -- -D warningscargo clippy --locked --lib --no-default-features -- -D warningscargo test --locked --all-features, thencargo test --lockedcargo doc --locked --no-deps --all-featureswithRUSTDOCFLAGS=-D warningscargo +1.89 check --locked --all-targets --all-features, the minimum supported Rust versiontests/runtime-adapterin its protocol-only and host-only configurations, and on Linux its musl guest-only one: rustfmt, Clippy, build, tests, and the 1.89 checkaci_edge_sandboxes, which builds onnvx, as its CI checks it, withACI_EDGE_SANDBOXES_AGENT_BUNDLE=skip: rustfmt, Clippy, tests,nvx.py test-agent-bundling, rustdoc, and its minimum supported Rust version, and on Linux its macOS checkThe guest module builds only on Linux, where these ran too:
check-nvx-rsruns it, andcargo check --locked --all-targets --all-features --target aarch64-apple-darwinpython3 scripts/nvx.py check-guest-binaries, which also runs the new tests forx86_64-unknown-linux-musl, thenbuild-guest-binaries --output DIRandtest-guest-binaries --binaries DIR. The nine guest binaries have the same instructions as those built fromdevat ed6a603, since nothing calls the new code yet. Each differs from them in one byte: the line number of a panic location insrc/guest/sys/mod.rs, whose re-exports grew by two lines.python3 -m compileall -q scripts,.github/skills/nvx-host-connect/scripts/test_hosts.py, thenvx.pyhelp commands, and Specula's testsOn Windows:
python scripts\nvx.py verifyandpython scripts\check_markdown_links.py. No Python file changed.read_diskon real block devices, on the Linux virtual machine as root, with a test program outside the repository:sfdisk(util-linux 2.40.2) wrote 8 MiB GPT disks, with text in the first partition and two layers, through loop devices with 512- and 4096-byte logical blocks, and read-only loop devices with the same block sizes then held them. Through each one,read_diskreturned the logical block size and size thatblockdevreports, the disk GUID, and each partition's LBAs and GUID assfdisk --dumplists them;read_first_partitionreturned the text; and the file's position was where it was before, also after eight threads had each calledread_disk200 times on the one file. A wrong expected disk GUID failed withGptError::DiskGuidMismatch, a disk read at the other block size failed at LBA 1, which held no GPT header there, and a regular file failed at its block size withENOTTY.CI runs the hypervisor matrix. This change adds no microVM scenario, and no guest binary calls the new code.