supermachine 0.7.82

Run any OCI/Docker image as a hardware-isolated microVM on macOS HVF (Linux KVM and Windows WHP in progress). Single library API, zero flags for the common case, sub-100 ms cold-restore from snapshot.
Documentation
//! DAX step 2 validation: mount a host directory into the guest over virtio-fs
//! (no DAX window yet) and read a file through it. Exercises the VirtioFs device
//! wired into kvm/run.rs + the sm.virtiofs init mount. Needs the virtio-fs/DAX
//! kernel (step 1) via SUPERMACHINE_KVM_KERNEL.
//!
//! Usage:
//!   SUPERMACHINE_KVM_KERNEL=/root/linux-6.12.30/arch/x86/boot/bzImage \
//!     cargo run --example kvm_virtiofs

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn main() {
    use std::time::Duration;
    use supermachine::vmm::resources::MountSpec;
    use supermachine::{Image, VmConfig};

    // The bundled kernel now has virtio-fs/FUSE/DAX built in, so no
    // SUPERMACHINE_KVM_KERNEL override is needed (it's still honored if set).

    // Host directory to share, with a known file.
    let host_dir = std::env::temp_dir().join("sm-vfs-host");
    let _ = std::fs::remove_dir_all(&host_dir);
    std::fs::create_dir_all(&host_dir).expect("mkdir host_dir");
    std::fs::write(host_dir.join("hello.txt"), b"virtiofs-works\n").expect("write file");
    std::fs::create_dir_all(host_dir.join("sub")).expect("mkdir sub");
    std::fs::write(host_dir.join("sub/nested.txt"), b"nested-ok\n").expect("write nested");

    // Bake a fresh image so SUPERMACHINE_KVM_KERNEL (the virtio-fs kernel) is the
    // one that boots — from_oci would reuse a cached bundled-kernel bake.
    let dest = std::env::temp_dir().join("sm-vfs-img");
    let _ = std::fs::remove_dir_all(&dest);
    let image = Image::bake_kvm_auto("alpine", &dest).expect("bake_kvm_auto");

    let cfg = VmConfig::new().with_virtiofs(MountSpec::new(
        host_dir.to_string_lossy().into_owned(),
        "smfs0",
        "/mnt/host",
    ));
    let vm = image.start(&cfg).expect("start");
    std::thread::sleep(Duration::from_millis(5000));

    let o = vm
        .exec_builder()
        .argv([
            "/bin/sh",
            "-c",
            "echo '== mount =='; mount | grep -E ' /mnt/host ' || echo not-mounted; \
             echo '== read =='; cat /mnt/host/hello.txt 2>&1; cat /mnt/host/sub/nested.txt 2>&1; \
             echo '== ls =='; ls /mnt/host",
        ])
        .output()
        .expect("exec");
    let out = String::from_utf8_lossy(&o.stdout);
    eprintln!("--- guest ---\n{out}");
    vm.stop().ok();

    // DAX is in play when the mount reports `dax=always` (init mounts `-o dax`);
    // run with SUPERMACHINE_FUSE_TRACE=1 to see the [dax] SETUPMAPPING/map host
    // logs that prove file pages were mapped zero-copy into the DAX window.
    let dax = out.contains("dax=always");
    let pass = out.contains("virtiofs-works") && out.contains("nested-ok");
    eprintln!(
        "=== KVM VIRTIO-FS MOUNT: {} (dax={}) ===",
        if pass { "PASS" } else { "FAIL" },
        dax
    );
}

#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
fn main() {
    eprintln!("kvm_virtiofs is Linux/x86_64 only");
}