Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions nvx-rs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -670,8 +670,9 @@ which OpenVMM restores from the snapshot, alone; a memory target in whole blocks
of `MEMORY_BLOCK_SIZE` from the template's RAM to its capacity; the clone's
image, which the check of its `DistroBinding` opens; its upper, either the
caller's scratch image, which the check of its `ScratchBinding` claims, and
which nothing formats, copies, or reads, or for an upper in RAM a fresh sparse
file, `clone-scratch.raw` in the sandbox's directory, which the release removes;
which nothing formats, copies, or reads, or RAM, whose restore declares the
template's scratch absent, so that OpenVMM attaches it with no file and the plan
creates none;
its export, if it has one, an `ExportPlan` that `filesystem::plan` made for the
container root, which must export exactly one directory, since the template's
dormant filesystem slot binds one directory and no file, and which must neither
Expand Down Expand Up @@ -706,12 +707,15 @@ and the guest's proxy URL; and the template's processors and the memory target.
The identity of a binding or of an export plan is the SHA-256 digest of a domain
and of its serde form, never of a file's content.

The image and the scratch device must present the `BlockGeometry` of the
template's, which a restore compares, and be, at the paths by which OpenVMM
opens them, the regular files that the checks found, which are not links or
other reparse points, and which no one else may change. Neither the image nor a
scratch image may be a file that the sandbox's store owns, such as
`clone-scratch.raw`, its log, or its records, by any path, since the store's
The image must present the logical and physical block sizes of the template's
placeholder and be no longer than it, since a restore presents every clone's
image at the placeholder's length, its capacity, and reads zeros past the end of
a shorter image, while a scratch image must present the `BlockGeometry` of the
template's scratch, its length included, which a restore compares; both must be,
at the paths by which OpenVMM opens them, the regular files that the checks
found, which are not links or other reparse points, and which no one else may
change. Neither the image nor a scratch image may be a file that the sandbox's
store owns, such as its log or its records, by any path, since the store's
transitions replace or remove them, and a link or a directory under one of the
store's names is refused.

Expand All @@ -724,7 +728,8 @@ writes the clone's activation record in its canonical encoding,
`clone-activation.bin`, from which a caller resends it unchanged; it listens for
the VMM's restore-ready event, at the socket `restore.sock` on Linux, and at a
named pipe of a random name on Windows; and it runs `supervisor::launch` with
OpenVMM's restore of the clone's devices and of the template's network, as its
OpenVMM's restore of the clone's devices, with `--restore-absent-scratch` for a
clone in RAM, and of the template's network, as its
key records it, unchanged, its export bound to the dormant slot, `--mount` with
the directory, and its hidden, re-exposed, and writable paths and its owner,
`--restore-snapshot` with the generation's snapshot in place, which no clone
Expand All @@ -745,8 +750,7 @@ claim's handle, which OpenVMM's open of the image would refuse.
A payload holds the sockets of its clones only while they lease it: the VMM
removes its socket as it exits, a stop or a recovery removes the one that an
abrupt exit leaves, and the release makes the socket's absence durable before
the lease ends, and removes the record and `restore.sock`, as it removes
`clone-scratch.raw`.
the lease ends, and removes the record and `restore.sock`.

`Restoring::activate` then runs the clone's restore sequence through the
adapter's framing of its control session, a `CloneControl`, by a
Expand Down
7 changes: 4 additions & 3 deletions nvx-rs/src/host/sandbox/distro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,10 @@ impl CheckedDistro {
/// its `st_blksize`, on Linux, of 4096 bytes on Windows, and of the logical block size on
/// other hosts, which must be a power of two of at least 512 bytes.
///
/// It reads the file's metadata alone. A restore of a template compares the geometry of each
/// of its block devices with the one that the template recorded, so the image of a clone must
/// present the geometry of the template's `distro`, as
/// It reads the file's metadata alone. A restore of a template presents its `distro` at the
/// geometry that the template recorded, the capacity of every clone's image, over an image
/// that may be shorter, so the image of a clone must be no longer than the template's
/// `distro`, with the same logical and physical block sizes, as
/// [`ClonePlan`](crate::host::template::ClonePlan) checks before the clone's launch.
///
/// Fails with [`ErrorKind::Unsupported`](crate::ErrorKind::Unsupported) for a length or a
Expand Down
3 changes: 2 additions & 1 deletion nvx-rs/src/host/store/lifecycle/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@ fn a_removal_is_refused_while_a_vm_or_a_launch_is_recorded() {
}
}

/// Writes the files that a clone keeps of its launch in the sandbox `dir`, its binding included.
/// Writes the files that a clone keeps of its launch in the sandbox `dir`, its binding included,
/// and the file of the scratch device that an earlier version left for a clone in RAM.
fn write_clone_files(dir: &Path) {
for name in [
CLONE_BINDING_NAME,
Expand Down
41 changes: 17 additions & 24 deletions nvx-rs/src/host/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
//! outcome.json the VMM's outcome report of the latest launch
//! .tmpXXXXXX the outcome report while the VMM writes it, which it then publishes
//! clone.json the binding of a clone to the generation of a template that it leases
//! clone-scratch.raw the file of the scratch device of a clone whose upper is in RAM, a
//! sparse file that the clone's plan creates
//! clone-scratch.raw the file of the scratch device that earlier versions created for a
//! clone whose upper is in RAM, which a release removes if one remains
//! clone-activation.bin the activation record of a clone, which its launch writes
//! clone-progress.log the progress log of a clone's launch and restore sequence
//! clone-failure.json the record of a clone's failure
Expand Down Expand Up @@ -297,11 +297,10 @@ pub const OUTCOME_NAME: &str = "outcome.json";
/// removes once its VM has exited. A [removal](self#removal) of the sandbox removes it first, and
/// makes its absence durable before the sandbox goes.
pub const CLONE_BINDING_NAME: &str = "clone.json";
/// Name of the file of the `scratch` block device of a clone whose upper is in RAM, which the
/// clone's restore attaches in place of the template's scratch, and which the guest leaves
/// unused: a sparse file of the template's scratch length, which
/// [`template::ClonePlan::new`](crate::host::template::ClonePlan::new) creates under the lease,
/// replacing one that an earlier clone of the sandbox left, and which
/// Name of the file of the `scratch` block device that earlier versions of this crate created for
/// a clone whose upper is in RAM, a sparse file of the template's scratch length. Such a clone now
/// restores with its scratch absent, and nothing creates the file, but a sandbox's directory may
/// still hold one that an earlier version left, which
/// [`template::Store::release`](crate::host::template::Store::release) removes once the clone's VM
/// has exited, as a [removal](self#removal) of the sandbox does.
pub const CLONE_SCRATCH_NAME: &str = "clone-scratch.raw";
Expand Down Expand Up @@ -332,9 +331,9 @@ pub const CLONE_PROGRESS_NAME: &str = "clone-progress.log";
/// [`template::Store::release`](crate::host::template::Store::release) removes, as a
/// [removal](self#removal) of the sandbox does.
pub const CLONE_FAILURE_NAME: &str = "clone-failure.json";
/// The files that the clone of a sandbox keeps of its launch, which a release removes once the
/// clone's VM has exited, as a [removal](self#removal) of the sandbox does, before the clone
/// binding.
/// The files that the clone of a sandbox keeps of its launch, and the file of the scratch device
/// that an earlier version created for a clone in RAM, which a release removes once the clone's VM
/// has exited, as a [removal](self#removal) of the sandbox does, before the clone binding.
const CLONE_FILE_NAMES: [&str; 5] = [
CLONE_SCRATCH_NAME,
CLONE_ACTIVATION_NAME,
Expand Down Expand Up @@ -583,12 +582,6 @@ impl SandboxStore {
self.path(CLONE_BINDING_NAME)
}

/// Returns the path of the file of the scratch device of a clone whose upper is in RAM,
/// [`CLONE_SCRATCH_NAME`].
pub fn clone_scratch_path(&self) -> PathBuf {
self.path(CLONE_SCRATCH_NAME)
}

/// Returns the path of the activation record of a clone, [`CLONE_ACTIVATION_NAME`].
pub fn clone_activation_path(&self) -> PathBuf {
self.path(CLONE_ACTIVATION_NAME)
Expand Down Expand Up @@ -859,14 +852,14 @@ impl LockedStore {
/// Removes what the clone of the sandbox kept of its launch in the sandbox's directory, whose
/// VM has exited, through `directory`, the handle of the directory that
/// [`open_dir`](Self::open_dir) returned: the file of its scratch device,
/// [`CLONE_SCRATCH_NAME`], its activation record, [`CLONE_ACTIVATION_NAME`], the socket of its
/// restore-ready event, [`RESTORE_READY_NAME`], its progress log, [`CLONE_PROGRESS_NAME`], and
/// the record of its failure, [`CLONE_FAILURE_NAME`]. A release, as a [removal](self#removal)
/// does, removes them before the clone binding, whose removal, once durable, makes theirs
/// durable too, since all are entries of the sandbox's directory. A file whose deletion is
/// pending, as a Windows file system without POSIX deletion leaves a removed file that another
/// handle holds, is removed already, so that a release that failed once it removed the file can
/// be retried.
/// [`CLONE_SCRATCH_NAME`], if an earlier version left one, its activation record,
/// [`CLONE_ACTIVATION_NAME`], the socket of its restore-ready event, [`RESTORE_READY_NAME`],
/// its progress log, [`CLONE_PROGRESS_NAME`], and the record of its failure,
/// [`CLONE_FAILURE_NAME`]. A release, as a [removal](self#removal) does, removes them before
/// the clone binding, whose removal, once durable, makes theirs durable too, since all are
/// entries of the sandbox's directory. A file whose deletion is pending, as a Windows file
/// system without POSIX deletion leaves a removed file that another handle holds, is removed
/// already, so that a release that failed once it removed the file can be retried.
pub(crate) fn remove_clone_files(&self, directory: &platform::Directory) -> Result<()> {
for name in CLONE_FILE_NAMES {
directory.remove_file(name).map_err(io_error(format!(
Expand Down
3 changes: 2 additions & 1 deletion nvx-rs/src/host/store/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,8 @@ fn the_files_that_a_clone_kept_of_its_launch_go_and_nothing_else() {
let (_directory, store) = store();
let locked = store.lock(None).unwrap();
for path in [
store.clone_scratch_path(),
// The file of the scratch device that an earlier version left for a clone in RAM.
store.dir().join(CLONE_SCRATCH_NAME),
store.clone_activation_path(),
store.clone_progress_path(),
store.clone_failure_path(),
Expand Down
Loading
Loading