From b42062a6b69ef287801ec72b3e5db0ea3d6d9212 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Mon, 24 Nov 2025 13:40:34 -0500 Subject: [PATCH] wip: add krun_add_disk3 API Signed-off-by: Jake Correnti --- include/libkrun.h | 16 ++++++ src/devices/src/virtio/block/device.rs | 19 +++++- src/devices/src/virtio/block/mod.rs | 15 +++++ src/libkrun/src/lib.rs | 80 +++++++++++++++++++++++++- src/vmm/src/vmm_config/block.rs | 9 ++- 5 files changed, 134 insertions(+), 5 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index af6e70982..115b5b8ff 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -217,6 +217,22 @@ int32_t krun_add_disk2(uint32_t ctx_id, uint32_t disk_format, bool read_only); + + #define KRUN_SYNC_NONE 0; + #define KRUN_SYNC_RELAXED 1; + #define KRUN_SYNC_FULL 2; + + #define KRUN_UNCACHED 0; + #define KRUN_CACHED 1; + + int32_t krun_add_disk3(uint32_t ctx_id, + const char *block_id, + const char *disk_path, + uint32_t disk_format, + bool read_only, + uint32_t cache_mode, + uint32_t sync_mode); + /** * NO LONGER SUPPORTED. DO NOT USE. * diff --git a/src/devices/src/virtio/block/device.rs b/src/devices/src/virtio/block/device.rs index c4999accc..b09199dc4 100644 --- a/src/devices/src/virtio/block/device.rs +++ b/src/devices/src/virtio/block/device.rs @@ -35,7 +35,10 @@ use super::{ Error, QUEUE_SIZES, SECTOR_SHIFT, SECTOR_SIZE, }; -use crate::virtio::{block::ImageType, ActivateError, InterruptTransport}; +use crate::virtio::{ + block::{CacheMode, ImageType, SyncMode}, + ActivateError, InterruptTransport, +}; /// Configuration options for disk caching. #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] @@ -208,6 +211,9 @@ impl Block { disk_image_path: String, disk_image_format: ImageType, is_disk_read_only: bool, + // TODO(jakecorrenti): should this even be here? Am i just re-writing essentially what's represented by `CacheType`? + cache_mode: CacheMode, + sync_mode: SyncMode, ) -> io::Result { let disk_image = OpenOptions::new() .read(true) @@ -218,7 +224,10 @@ impl Block { let file_opts = StorageOpenOptions::new() .write(!is_disk_read_only) - .filename(disk_image_path); + .filename(disk_image_path) + .direct(cache_mode == CacheMode::Uncached); + + // TODO(jakecorrenti): how do I do a partial fsync on linux to handle that OS? #[cfg(target_os = "macos")] let file_opts = file_opts.relaxed_sync(true); let file = ImagoFile::open_sync(file_opts)?; @@ -248,10 +257,14 @@ impl Block { DiskProperties::new(Arc::clone(&disk_image), disk_image_id.clone(), cache_type)?; let mut avail_features = (1u64 << VIRTIO_F_VERSION_1) - | (1u64 << VIRTIO_BLK_F_FLUSH) + // | (1u64 << VIRTIO_BLK_F_FLUSH) | (1u64 << VIRTIO_BLK_F_SEG_MAX) | (1u64 << VIRTIO_RING_F_EVENT_IDX); + if sync_mode != SyncMode::None { + avail_features |= 1u64 << VIRTIO_BLK_F_FLUSH; + } + if is_disk_read_only { avail_features |= 1u64 << VIRTIO_BLK_F_RO; }; diff --git a/src/devices/src/virtio/block/mod.rs b/src/devices/src/virtio/block/mod.rs index 7fe4fb4d4..a0c56d59d 100644 --- a/src/devices/src/virtio/block/mod.rs +++ b/src/devices/src/virtio/block/mod.rs @@ -39,3 +39,18 @@ pub enum ImageType { Raw, Qcow2, } + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub enum CacheMode { + Uncached, + #[default] + Cached, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub enum SyncMode { + None, + Relaxed, + #[default] + Full, +} diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index b5df8c298..bd20c276e 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -3,7 +3,7 @@ extern crate log; use crossbeam_channel::unbounded; #[cfg(feature = "blk")] -use devices::virtio::block::ImageType; +use devices::virtio::block::{CacheMode, ImageType, SyncMode}; #[cfg(feature = "gpu")] use devices::virtio::gpu::display::DisplayInfo; #[cfg(feature = "net")] @@ -671,6 +671,8 @@ pub unsafe extern "C" fn krun_add_disk( disk_image_path: disk_path.to_string(), disk_image_format: ImageType::Raw, is_disk_read_only: read_only, + cache_mode: CacheMode::Cached, + sync_mode: SyncMode::Full, }; cfg.add_block_cfg(block_device_config); } @@ -718,6 +720,78 @@ pub unsafe extern "C" fn krun_add_disk2( disk_image_path: disk_path.to_string(), disk_image_format: format, is_disk_read_only: read_only, + cache_mode: CacheMode::Cached, + sync_mode: SyncMode::Full, + }; + cfg.add_block_cfg(block_device_config); + } + Entry::Vacant(_) => return -libc::ENOENT, + } + + KRUN_SUCCESS +} + +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +#[cfg(feature = "blk")] +pub unsafe extern "C" fn krun_add_disk3( + ctx_id: u32, + c_block_id: *const c_char, + c_disk_path: *const c_char, + disk_format: u32, + read_only: bool, + cache_mode: u32, + sync_mode: u32, +) -> i32 { + let disk_path = match CStr::from_ptr(c_disk_path).to_str() { + Ok(disk) => disk, + Err(_) => return -libc::EINVAL, + }; + + let block_id = match CStr::from_ptr(c_block_id).to_str() { + Ok(block_id) => block_id, + Err(_) => return -libc::EINVAL, + }; + + let format = match disk_format { + 0 => ImageType::Raw, + 1 => ImageType::Qcow2, + _ => { + // Do not continue if the user cannot specify a valid disk format + return -libc::EINVAL; + } + }; + + let cache_mode = match cache_mode { + 0 => CacheMode::Uncached, + 1 => CacheMode::Cached, + _ => { + // Do not continue if the user cannot specify a valid cache mode + return -libc::EINVAL; + } + }; + + let sync_mode = match sync_mode { + 0 => SyncMode::None, + 1 => SyncMode::Relaxed, + 2 => SyncMode::Full, + _ => { + // Do not continue if the user cannot specify a valid sync mode + return -libc::EINVAL; + } + }; + + match CTX_MAP.lock().unwrap().entry(ctx_id) { + Entry::Occupied(mut ctx_cfg) => { + let cfg = ctx_cfg.get_mut(); + let block_device_config = BlockDeviceConfig { + block_id: block_id.to_string(), + cache_type: CacheType::auto(disk_path), + disk_image_path: disk_path.to_string(), + disk_image_format: format, + is_disk_read_only: read_only, + cache_mode, + sync_mode, }; cfg.add_block_cfg(block_device_config); } @@ -745,6 +819,8 @@ pub unsafe extern "C" fn krun_set_root_disk(ctx_id: u32, c_disk_path: *const c_c disk_image_path: disk_path.to_string(), disk_image_format: ImageType::Raw, is_disk_read_only: false, + cache_mode: CacheMode::Cached, + sync_mode: SyncMode::Full, }; cfg.set_root_block_cfg(block_device_config); } @@ -772,6 +848,8 @@ pub unsafe extern "C" fn krun_set_data_disk(ctx_id: u32, c_disk_path: *const c_c disk_image_path: disk_path.to_string(), disk_image_format: ImageType::Raw, is_disk_read_only: false, + cache_mode: CacheMode::Cached, + sync_mode: SyncMode::Full, }; cfg.set_data_block_cfg(block_device_config); } diff --git a/src/vmm/src/vmm_config/block.rs b/src/vmm/src/vmm_config/block.rs index 13a6f6a7b..0f7ba0244 100644 --- a/src/vmm/src/vmm_config/block.rs +++ b/src/vmm/src/vmm_config/block.rs @@ -2,7 +2,10 @@ use std::collections::VecDeque; use std::fmt; use std::sync::{Arc, Mutex}; -use devices::virtio::{block::ImageType, Block, CacheType}; +use devices::virtio::{ + block::{CacheMode, ImageType, SyncMode}, + Block, CacheType, +}; #[derive(Debug)] pub enum BlockConfigError { @@ -28,6 +31,8 @@ pub struct BlockDeviceConfig { pub disk_image_path: String, pub disk_image_format: ImageType, pub is_disk_read_only: bool, + pub cache_mode: CacheMode, + pub sync_mode: SyncMode, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -63,6 +68,8 @@ impl BlockBuilder { config.disk_image_path, config.disk_image_format, config.is_disk_read_only, + config.cache_mode, + config.sync_mode, ) .map_err(BlockConfigError::CreateBlockDevice) }