Skip to content

feat(block): support live capacity growth - #124

Merged
appcypher merged 38 commits into
krunfrom
appcypher/live-block-capacity-growth
Sep 7, 2026
Merged

feat(block): support live capacity growth#124
appcypher merged 38 commits into
krunfrom
appcypher/live-block-capacity-growth

Conversation

@appcypher

Copy link
Copy Markdown
Member

TL;DR

Add grow-only capacity updates for an owned writable block device while the VM is paused. The guest receives a virtio configuration notification after the disk and request bounds have been updated.

Description

  • Add VmControl::grow_block_capacity(device_id, size_bytes) for raw and qcow2 backends.
  • Drain the block worker before changing capacity and preserve its backing chain, writeback policy, and host handles.
  • Reject shrinking, unaligned sizes, read-only devices, and updates outside a paused boundary.
  • Leave filesystem expansion and recovery after partial I/O failure to the caller.
  • Stack on feat(state): add reversible virtio device state #122 without importing unrelated main changes.
let pause = control.pause()?;
control.grow_block_capacity("vdb", 8 * 1024 * 1024 * 1024)?;
control.resume(pause)?;
// The caller then expands the guest filesystem and verifies completion.

Test Plan

  • cargo test --offline -p msb_krun_devices --features blk passes 135 tests.
  • cargo check --offline -p msb_krun --features blk succeeds.
  • cargo fmt --all -- --check and git diff --check pass.
  • macOS/HVF managed and flat roots pass raw, qcow2, repeated, compacted, partial-group, stopped, deferred, and old/new full-restore checks through the caller runtime.
  • Linux/KVM and Windows/WHP live qualification (source transfer awaits owner approval).

Add generation-scoped pause and resume barriers with bounded execution-state
capture and restore for the qualified KVM, HVF, and WHP backends.

Introduce request-scoped memory access epochs that drain host virtio writers,
combine backend and host dirty coverage, and stream complete or retained-
baseline incremental memory generations with explicit publish and abandon
semantics.

Expose eager construction restore and an event-driven Running wait through
VmControl, including conservative transition publication and safe complete-
capture fallback when dirty coverage cannot be trusted.
Capture and restore exact virtio-mmio, queue, and block state at a complete paused boundary. Stop block workers before admitting new descriptors and return their queue after terminal completion and durability fencing.

Add caller-resolved raw and qcow2 dependency chains that deny implicit path opening, plus validated backend replacement while a device remains quiesced. Preserve capacity, identity, feature, cache, and read-only compatibility across replacement.
Expose a config-only virtio device for publishing immutable generation identifiers and observing exact guest processing acknowledgements. Provide monotonic requests, idempotent retries, supersession outcomes, and an event-driven waiter without adding work to ordinary execution or I/O paths.

Attach the device after existing virtio devices to preserve their established MMIO and interrupt allocation order, and surface the control operations through VmControl.
Expose deterministic device inventory and bounded generic transport state so callers can admit and capture reversible device boundaries.

Stop and join console, network, and vsock workers before returning queue ownership. Preserve source-local network continuation state, make backend support explicit, and add clean boundaries for balloon, CPU, memory, metrics, RNG, and VM generation devices.

Add deterministic codec and lifecycle coverage for malformed state, blocked console workers, network worker stop/resume, and vsock reactivation.
Stop the virtio-fs worker at a descriptor ownership boundary and return its queues and event handles to the transport. Prioritize stop over queue events so checkpoint pause work is bounded by a request already in progress instead of the guest backlog.\n\nCover quiesce and reactivation with a lifecycle test.
Complete a consumed RX descriptor with zero length before returning on EOF, and give stop requests priority over dequeuing new TX work. Include queue indices in transport-state capture errors so an invalid device boundary identifies the responsible queue.
Remember which console ports owned host workers before reversible quiescence and restart them directly when the device is reactivated. The guest sends PORT_OPEN only during initial negotiation, so waiting for it again leaves agent traffic stalled after resume.
Preserve userspace IOAPIC registers and pending lines alongside the KVM
clock when x86 uses split irqchip mode. Keep the existing PIT, PIC, and
in-kernel IOAPIC capture for the kernel-owned model.

Reject execution-state restoration across mismatched interrupt-controller
models and rebuild host routing from restored guest-visible registers.
Permit a bounded buffered device to replace its backend only when the replacement uses direct I/O. Preserve the negotiated guest contract while dropping raw-offset writeback accounting that cannot describe formatted storage.
Reserve a distinct muxer stop token instead of colliding with the Windows epoll control token. Reject the matching proxy port tuple and register the stop handle before activation succeeds so quiescence cannot wait on an unreachable worker.
Avoid the token reserved by the Windows epoll control notifier so the virtio-net worker can register and observe its stop event during reversible quiescence.
Restore captured device state after memory and execution reconstruction but before the first guest instruction. Allow restore coordinators to publish the constructed VM at an explicit paused boundary and wait for that boundary without polling.\n\nOrdinary boot remains unchanged unless the caller opts into the activation gate.
Keep the time-sync condition variable available on macOS without leaving an unused import on Linux. Apply the workspace formatter to the two virtio-fs files reported by CI so the checkpoint stack passes its formatting gate.
Compile the deterministic MMIO inventory only with block support, which is its sole caller. Document and permit the intentionally inline KVM checkpoint state rather than adding heap indirection to a rarely constructed ABI-shaped value.
Scope KVM checkpoint imports and mapped host addresses to the architectures and feature profiles that consume them. Keep the cross-architecture device inventory exhaustive without treating x86's single configured variant as a warning.
Compile the pause-generation implementation and its I/O dependency only for host-readable VM profiles, matching the public checkpoint API's existing TEE exclusion.
Capture and restore host-bound virtio device state through bounded, device-specific payloads, including console, virtio-fs, block feature contracts, VM generation state, and backend execution details.\n\nReconstruct destination-local filesystem providers and worker resources, preserve Linux interrupt and IA32_XSS state, and make vCPU teardown deterministic across KVM, HVF, and WHP.
Add a latched host-time sample to the generation device and require the
kernel to acknowledge identity and clock processing together. Expose
clock capability and immediate failure through VmControl.

Rebase HVF virtual timer offsets with one VM-wide counter displacement
and keep KVM from injecting offline time into its restored clock.

Qualify delayed restore, timer semantics, and repeated activation on
macOS and Linux with the matching guest driver.
Grow a drained writable raw or qcow2 backend without changing its backing chain. Update request bounds and notify the guest through the virtio configuration interrupt. The caller owns filesystem expansion and forward recovery after partial I/O failure.

Add coverage for preserved data, zero-filled growth, repeated targets, read-only rejection, and shrink rejection. Device tests and managed/flat macOS integration pass.
Replace request-count-sized host dirty logs with RAM-sized page bitmaps.
Invalidate baseline coverage after partial backend failures and reconcile
tracking before another baseline or vCPU resume can succeed.

Add release benchmarks, full-versus-delta live checks, and an HVF fault
interposer. Record macOS results and outstanding Linux/WHP qualification.
Fix the Linux architecture and TEE import warnings identified in CI.
Correct partial-page merging in the comparison sink and make the harness build on Windows. Record Linux and Windows live results, exclusions, and remaining qualification gaps.

Exercise a real second-slot KVM dirty-log failure and recovery. Gate pause-generation helpers and io imports consistently for TEE builds.
Keep Duration behind the same feature guard as VM generation control. Verify AMD-SEV and TDX builds with warnings denied.
Recognize the stable virtio-fs device ID in framing without importing the disabled filesystem backend in TEE builds. AMD-SEV and TDX Clippy checks pass.
Exercise Linux disable failures and Windows initial-arm and disable mapping failures on live VMs. Verify baseline invalidation, rebase, resume, and post-recovery delta equality.

Record 30 passing fault cases and the separate Windows host-read failure before tracking starts. Keep WHP fault instrumentation as a test-only patch.
Carry the validated parent build fix into the live capacity branch. This integration does not change memory recovery or VM resume ordering.
Integrate the memory tracking recovery prerequisite. Reconcile mappings before device workers reopen and release vCPUs last, retaining the paused boundary if repair fails.
Add an opt-in device-enabled harness and record seven passing integrated HVF fault runs. Track the minimal filesystem serialization limitation explicitly and retain Linux/WHP integration qualification as pending.
Carry the updated execution and device prerequisites into the live capacity stack without changing capacity-growth behavior. Local blk-feature Clippy and formatting checks pass; integrated remote live testing remains pending.
@appcypher

Copy link
Copy Markdown
Member Author

Integrated recovery qualification completed at head 6b61025 on 2026-09-07: six Linux/KVM and six native Windows ARM64/WHP live fault runs passed, covering one/two vCPUs with three repetitions each. Device workers were quiesced before partial tracking-disable/remap failure; resume-before-rebase recovered, and subsequent deltas matched fresh full RAM with zero mismatches. This tests the inherited #122 ordering on the actual #124 integration. All nine CI checks pass. This batch is recovery qualification, not a new capacity-growth benchmark. Minimal filesystem durable serialization and the separate Windows pre-tracking host-read failure remain explicitly outside these passing assertions. Earlier README remote-approval pending entries are superseded by these results.

Record the squash-merged krun baseline as an ancestor. Its tree is identical to the execution baseline already included here; preserve the qualified device-state tree without changes.
Reconcile the generation coordination APIs with the execution and memory APIs now merged into krun. Preserve both interfaces and keep the generation PR scoped to its original functionality.
Retain the already-qualified generation and clock implementation while recording the updated generation branch as a parent. The resulting source tree is unchanged.
Integrate the updated parent history after the execution baseline squash merge. Preserve the qualified capacity-growth tree unchanged.
Record the squash-merged generation baseline as an ancestor. Verify its tree matches the generation parent already integrated here and preserve the qualified device-state tree unchanged.
Integrate the repaired device-state parent after the generation baseline squash merge. Preserve the qualified capacity-growth tree without source changes.
Base automatically changed from appcypher/virtio-block-state to krun September 7, 2026 00:21
Record the squash-merged device-state baseline as an ancestor. Its tree matches the parent already included here; preserve the qualified capacity-growth implementation without source changes.
@appcypher
appcypher merged commit d691206 into krun Sep 7, 2026
9 checks passed
@appcypher
appcypher deleted the appcypher/live-block-capacity-growth branch September 7, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant