pub struct CowManager { /* private fields */ }Expand description
Manages template loop devices and per-sandbox dm-snapshot lifecycle.
Implementations§
Source§impl CowManager
impl CowManager
Sourcepub fn adopt(&self, handle: &CowHandle) -> Result<(), SnapshotError>
pub fn adopt(&self, handle: &CowHandle) -> Result<(), SnapshotError>
Re-register the CoW resources of a sandbox whose VM is still running.
Verifies the dm device is present and that the template’s loop device
is still attached and still backs handle.template_path, then takes
the template refcount the handle is documented to own — which is what
keeps Self::reconcile_stale from detaching a shared loop out from
under a live rootfs, and what makes the eventual teardown balance.
Call before Self::reconcile_stale, once per adopted sandbox. A
failed verification is an error rather than a silent skip: the
caller’s fallback is to tear the sandbox down, and it has to know.
Sourcepub fn reconcile_stale(
&self,
keep_cow_files: &HashSet<String>,
live_devices: &HashSet<String>,
) -> Result<(), SnapshotError>
pub fn reconcile_stale( &self, keep_cow_files: &HashSet<String>, live_devices: &HashSet<String>, ) -> Result<(), SnapshotError>
Remove orphaned dm-snapshot devices, COW files, and template loop
devices left over from a previous crash. Called after orphaned
Firecracker processes are dead — every one of them except the
sandboxes named by live_devices, whose VMs are still running and
were reclaimed by Self::adopt. It is synchronous because every
command is short and startup is already gated on reconciliation.
Both sets are keyed by the resource owner — the id in
arcbox-cow-{owner}.img and arcbox-snap-{owner} — which for a
sandbox that adopted a pre-warmed pool slot is the slot’s id, not the
sandbox’s.
keep_cow_files names owners whose COW file is retained state, not
an orphan: a paused sandbox keeps its (detached) overlay on disk so
Resume can re-assemble the dm-snapshot with every written block
intact (CORE-21). Deleting those files here would silently destroy a
paused sandbox’s disk across an agent restart.
live_devices names owners whose dm-snapshot is in use by a running
VM. The two sets stay separate because they describe genuinely
different states: a paused sandbox’s device was already torn down at
pause, so reading its retained file as a live device would leave the
device of a sandbox that crashed mid-pause unreaped. The other
direction does hold — a live device’s overlay is its running disk —
so those files are kept whether or not the caller lists them twice.
pub async fn cleanup_setup_orphan( &self, sandbox_id: &str, ) -> Result<(), SnapshotError>
Source§impl CowManager
impl CowManager
Sourcepub fn new(options: CowOptions) -> Result<CowManager, SnapshotError>
pub fn new(options: CowOptions) -> Result<CowManager, SnapshotError>
Create a new manager over options; COW files are stored under
{data_dir}/cow/.
Sourcepub async fn setup(
&self,
sandbox_id: &str,
rootfs_path: &str,
) -> Result<CowHandle, SnapshotError>
pub async fn setup( &self, sandbox_id: &str, rootfs_path: &str, ) -> Result<CowHandle, SnapshotError>
Create a dm-snapshot for sandbox_id using rootfs_path as template.
Returns a CowHandle whose dm_device field can be passed to
Firecracker as the rootfs block device.
Sourcepub async fn reattach(
&self,
sandbox_id: &str,
rootfs_path: &str,
) -> Result<CowHandle, SnapshotError>
pub async fn reattach( &self, sandbox_id: &str, rootfs_path: &str, ) -> Result<CowHandle, SnapshotError>
Re-assemble the dm-snapshot for a paused sandbox from its preserved COW file (CORE-21 resume).
The snapshot table uses persistent mode (P), so the exception store
in the retained overlay carries every block the sandbox wrote before
it was paused. Unlike Self::setup, the COW file must already
exist and match the template size, and no failure path deletes it —
the overlay is the sandbox’s disk.
Sourcepub async fn teardown(&self, handle: &CowHandle)
pub async fn teardown(&self, handle: &CowHandle)
Tear down a dm-snapshot, logging any incomplete cleanup.
Sourcepub async fn teardown_checked(
&self,
handle: &CowHandle,
) -> Result<(), SnapshotError>
pub async fn teardown_checked( &self, handle: &CowHandle, ) -> Result<(), SnapshotError>
Tear down a dm-snapshot and report whether every owned resource was released. Crash reconciliation and durable Remove use this result to avoid declaring cleanup complete when a retry is still required.
Sourcepub async fn detach_keep_cow(
&self,
handle: &CowHandle,
) -> Result<(), SnapshotError>
pub async fn detach_keep_cow( &self, handle: &CowHandle, ) -> Result<(), SnapshotError>
Tear down the dm device and COW loop but keep the COW file on disk.
This is the pause half of CORE-21: the persistent (P) exception
store in the retained file preserves every written block, and
Self::reattach re-assembles the identical device on resume. A
failed step keeps the handle valid for retry, exactly like
Self::teardown_checked.
Sourcepub async fn remove_preserved_cow(
&self,
sandbox_id: &str,
) -> Result<(), SnapshotError>
pub async fn remove_preserved_cow( &self, sandbox_id: &str, ) -> Result<(), SnapshotError>
Delete the COW file a pause left behind (sandbox Remove / TTL).
Idempotent: a missing file is success. Any loop still backing the file is detached first so the unlink actually frees the space.