Skip to content

Commit

Permalink
Add krun_add_disk() method; deprecate set_*_disk
Browse files Browse the repository at this point in the history
This generalizes over krun_set_{root,data}_disk(). Notably:

* It allows arbitrarily many disk images.
* It allows mounting disks read-only.
* It does not assume specific root/data semantics.
* It allows setting labels.

To implement, we refactor a bit the existing handling. The set_*_disk
methods are deprecated due to the above issues, and will be removed in a
future major version. For now both APIs are supported but are mutually
exclusive.

Signed-off-by: Alyssa Rosenzweig <[email protected]>
  • Loading branch information
alyssarosenzweig committed Sep 17, 2024
1 parent c79ffd7 commit 3db55d7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 19 deletions.
27 changes: 25 additions & 2 deletions include/libkrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ int32_t krun_set_vm_config(uint32_t ctx_id, uint8_t num_vcpus, uint32_t ram_mib)
int32_t krun_set_root(uint32_t ctx_id, const char *root_path);

/**
* DEPRECATED. Use krun_add_disk instead.
*
* Sets the path to the disk image that contains the file-system to be used as root for the microVM.
* The only supported image format is "raw".
*
Expand All @@ -77,8 +79,10 @@ int32_t krun_set_root(uint32_t ctx_id, const char *root_path);
int32_t krun_set_root_disk(uint32_t ctx_id, const char *disk_path);

/**
* Sets the path to the disk image that contains the file-system to be used as a data partition for the microVM.
* The only supported image format is "raw".
* DEPRECATED. Use krun_add_disk instead.
*
* Sets the path to the disk image that contains the file-system to be used as
* a data partition for the microVM. The only supported image format is "raw".
*
* Arguments:
* "ctx_id" - the configuration context ID.
Expand All @@ -90,6 +94,25 @@ int32_t krun_set_root_disk(uint32_t ctx_id, const char *disk_path);
*/
int32_t krun_set_data_disk(uint32_t ctx_id, const char *disk_path);

/**
* Adds a disk image to be used as a general partition for the microVM.
*
* This API is mutually exclusive with the deprecated krun_set_root_disk and
* krun_set_data_disk methods and must not be used together.
*
* Arguments:
* "ctx_id" - the configuration context ID.
* "block_id" - a null-terminated string representing the partition.
* "disk_path" - a null-terminated string representing the path leading to the disk image that
* contains the root file-system.
* "read_only" - whether the mount should be read-only. Required if the caller does not have
* write permissions (for disk images in /usr/share).
*
* Returns:
* Zero on success or a negative error number on failure.
*/
int32_t krun_add_disk(uint32_t ctx_id, const char *block_id, const char *disk_path, bool read_only);

/**
* NO LONGER SUPPORTED. DO NOT USE.
*
Expand Down
75 changes: 58 additions & 17 deletions src/libkrun/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct ContextConfig {
net_cfg: NetworkConfig,
mac: Option<[u8; 6]>,
#[cfg(feature = "blk")]
block_cfgs: Vec<BlockDeviceConfig>,
#[cfg(feature = "blk")]
root_block_cfg: Option<BlockDeviceConfig>,
#[cfg(feature = "blk")]
data_block_cfg: Option<BlockDeviceConfig>,
Expand Down Expand Up @@ -156,13 +158,13 @@ impl ContextConfig {
}

#[cfg(feature = "blk")]
fn set_root_block_cfg(&mut self, block_cfg: BlockDeviceConfig) {
self.root_block_cfg = Some(block_cfg);
fn add_block_cfg(&mut self, block_cfg: BlockDeviceConfig) {
self.block_cfgs.push(block_cfg);
}

#[cfg(feature = "blk")]
fn get_root_block_cfg(&self) -> Option<BlockDeviceConfig> {
self.root_block_cfg.clone()
fn set_root_block_cfg(&mut self, block_cfg: BlockDeviceConfig) {
self.root_block_cfg = Some(block_cfg);
}

#[cfg(feature = "blk")]
Expand All @@ -171,8 +173,20 @@ impl ContextConfig {
}

#[cfg(feature = "blk")]
fn get_data_block_cfg(&self) -> Option<BlockDeviceConfig> {
self.data_block_cfg.clone()
fn get_block_cfg(&self) -> Vec<BlockDeviceConfig> {
// For backwards compat, when cfgs is empty (the new API is not used), this needs to be
// root and then data, in that order. Also for backwards compat, root/data are setters and
// need to discard redundant calls. So we have simple setters above and fix up here.
//
// When the new API is used, this is simpler.
if self.block_cfgs.is_empty() {
[&self.root_block_cfg, &self.data_block_cfg]
.into_iter()
.filter_map(|cfg| cfg.clone())
.collect()
} else {
self.block_cfgs.clone()
}
}

fn set_net_cfg(&mut self, net_cfg: NetworkConfig) {
Expand Down Expand Up @@ -484,12 +498,47 @@ pub unsafe extern "C" fn krun_set_mapped_volumes(
#[allow(clippy::missing_safety_doc)]
#[no_mangle]
#[cfg(feature = "blk")]
pub unsafe extern "C" fn krun_set_root_disk(ctx_id: u32, c_disk_path: *const c_char) -> i32 {
pub unsafe extern "C" fn krun_add_disk(
ctx_id: u32,
c_block_id: *const c_char,
c_disk_path: *const c_char,
read_only: bool,
) -> 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,
};

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::Writeback,
disk_image_path: disk_path.to_string(),
is_disk_read_only: read_only,
};
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_set_root_disk(ctx_id: u32, c_disk_path: *const c_char) -> i32 {
let disk_path = match CStr::from_ptr(c_disk_path).to_str() {
Ok(disk) => disk,
Err(_) => return -libc::EINVAL,
};

match CTX_MAP.lock().unwrap().entry(ctx_id) {
Entry::Occupied(mut ctx_cfg) => {
Expand Down Expand Up @@ -1009,17 +1058,9 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
};

#[cfg(feature = "blk")]
if let Some(block_cfg) = ctx_cfg.get_root_block_cfg() {
if ctx_cfg.vmr.add_block_device(block_cfg).is_err() {
error!("Error configuring virtio-blk for root block");
return -libc::EINVAL;
}
}

#[cfg(feature = "blk")]
if let Some(block_cfg) = ctx_cfg.get_data_block_cfg() {
for block_cfg in ctx_cfg.get_block_cfg() {
if ctx_cfg.vmr.add_block_device(block_cfg).is_err() {
error!("Error configuring virtio-blk for data block");
error!("Error configuring virtio-blk for block");
return -libc::EINVAL;
}
}
Expand Down

0 comments on commit 3db55d7

Please sign in to comment.