Skip to main content

CowManager

Struct CowManager 

Source
pub struct CowManager { /* private fields */ }
Expand description

Manages template loop devices and per-sandbox dm-snapshot lifecycle.

Implementations§

Source§

impl CowManager

Source

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.

Source

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.

Source

pub async fn cleanup_setup_orphan( &self, sandbox_id: &str, ) -> Result<(), SnapshotError>

Source§

impl CowManager

Source

pub fn new(options: CowOptions) -> Result<CowManager, SnapshotError>

Create a new manager over options; COW files are stored under {data_dir}/cow/.

Source

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.

Source

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.

Source

pub async fn teardown(&self, handle: &CowHandle)

Tear down a dm-snapshot, logging any incomplete cleanup.

Source

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.

Source

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.

Source

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.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more