Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] vhost-user-blk: initial implementation #4069

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
337d901
refactor(vmm): use thiserror for ActivateError
kalyazin Aug 7, 2023
f1b9741
refactor(vmm): use thiserror for PersistError
kalyazin Aug 18, 2023
d3bff83
feat(vm_memory): map guest memory as shared
kalyazin Jul 26, 2023
d4fa69e
feat(vmm): use memfd for guest memory
kalyazin Jul 26, 2023
5e1fd2c
test(jailer): remove test_negative_file_size_limit
kalyazin Sep 12, 2023
ae3abb9
feat(vmm): add can_update_interrupt_status method to VirtioDevice
kalyazin Aug 1, 2023
58c3914
refactor(vmm): add device subtype
kalyazin Jul 17, 2023
4cf12eb
refactor(vmm): move block to block/file
kalyazin Jul 17, 2023
5892523
refactor(vmm): rename host-file-backed block device structs
kalyazin Jul 17, 2023
5c38d16
refactor(vmm): extract common disk functionality
kalyazin Jul 19, 2023
1532d64
refactor(vmm): introduce block device enum
kalyazin Jul 21, 2023
a94efb2
feat(vmm): add new put API for /drives
kalyazin Jul 24, 2023
8f1a4b1
feat(vmm): add new patch API for /drives
kalyazin Jul 24, 2023
5ca8b68
refactor(api_server): maintain alphabetical order in Drive
kalyazin Aug 22, 2023
5fa652f
feat(api_server): update api for file-backed drives
kalyazin Jul 24, 2023
87b34e2
feat(vmm): add block device subtypes list in device state
kalyazin Aug 7, 2023
7c2bf31
feat(vmm): make avail_idx queue method public
kalyazin Aug 18, 2023
301b38a
feat(vmm): add vhost-user protocol implementaion
kalyazin Aug 18, 2023
65be7ae
feat(vmm): add vhost-user-blk device
kalyazin Aug 18, 2023
d68871c
feat(api_server): add put api for vhost-user drives
kalyazin Aug 22, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions resources/seccomp/aarch64-unknown-linux-musl.json
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,10 @@
{
"syscall": "sched_yield",
"comment": "Used by the rust standard library in std::sync::mpmc. Firecracker uses mpsc channels from this module for inter-thread communication"
},
{
"syscall": "sendmsg",
"comment": "Used by vhost-user frontend to communicate with the backend"
}
]
}
Expand Down
4 changes: 4 additions & 0 deletions resources/seccomp/x86_64-unknown-linux-musl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,10 @@
{
"syscall": "sched_yield",
"comment": "Used by the rust standard library in std::sync::mpmc. Firecracker uses mpsc channels from this module for inter-thread communication"
},
{
"syscall": "sendmsg",
"comment": "Used by vhost-user frontend to communicate with the backend"
}
]
}
Expand Down
13 changes: 10 additions & 3 deletions src/api_server/src/request/drive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,19 @@
));
}

// Give priority to the file configuration and fall back to the legacy parameters.
let (path_on_host, rate_limiter) = match &block_device_update_cfg.file {
Some(file) => (&file.path_on_host, file.rate_limiter),

Check warning on line 69 in src/api_server/src/request/drive.rs

View check run for this annotation

Codecov / codecov/patch

src/api_server/src/request/drive.rs#L69

Added line #L69 was not covered by tests
None => (
&block_device_update_cfg.path_on_host,
block_device_update_cfg.rate_limiter,
),
};

// Validate request - we need to have at least one parameter set:
// - path_on_host
// - rate_limiter
if block_device_update_cfg.path_on_host.is_none()
&& block_device_update_cfg.rate_limiter.is_none()
{
if path_on_host.is_none() && rate_limiter.is_none() {
METRICS.patch_api_requests.drive_fails.inc();
return Err(Error::Generic(
StatusCode::BadRequest,
Expand Down
90 changes: 80 additions & 10 deletions src/api_server/swagger/firecracker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -856,9 +856,7 @@ definitions:
type: object
required:
- drive_id
- is_read_only
- is_root_device
- path_on_host
properties:
drive_id:
type: string
Expand All @@ -868,8 +866,26 @@ definitions:
Represents the caching strategy for the block device.
enum: ["Unsafe", "Writeback"]
default: "Unsafe"
file:
description:
Configuration for the host-file-backed device.
If provided, overrides `io_engine`, `is_read_only`, `path_on_host` and `rate_limiter`.
$ref: "#/definitions/FileConfig"
io_engine:
type: string
description:
Type of the IO engine used by the device. "Async" is supported on
host kernels newer than 5.10.51.
This parameter has been deprecated since v1.6.0.
Use parameters in `file` instead.
enum: ["Sync", "Async"]
default: "Sync"
is_read_only:
type: boolean
description:
The drive is read only.
This parameter has been deprecated since v1.6.0.
Use parameters in `file` instead.
is_root_device:
type: boolean
partuuid:
Expand All @@ -880,17 +896,19 @@ definitions:
field is true.
path_on_host:
type: string
description: Host level path for the guest drive
description:
Host level path for the guest drive.
This parameter has been deprecated since v1.6.0.
Use parameters in `file` instead.
rate_limiter:
description:
This parameter has been deprecated since v1.6.0.
Use parameters in `file` instead.
$ref: "#/definitions/RateLimiter"
io_engine:
type: string
vhost_user:
description:
Type of the IO engine used by the device. "Async" is supported on
host kernels newer than 5.10.51.
enum: ["Sync", "Async"]
default: "Sync"

Configuration for the vhost-user-backed device.
$ref: "#/definitions/VhostUserConfig"
Error:
type: object
properties:
Expand All @@ -899,6 +917,29 @@ definitions:
description: A description of the error condition
readOnly: true

FileConfig:
type: object
required:
- is_read_only
- path_on_host
properties:
is_read_only:
description:
The drive is read only.
type: boolean
io_engine:
type: string
description:
Type of the IO engine used by the device. "Async" is supported on
host kernels newer than 5.10.51.
enum: ["Sync", "Async"]
default: "Sync"
path_on_host:
type: string
description: Host level path for the guest drive
rate_limiter:
$ref: "#/definitions/RateLimiter"

FullVmConfiguration:
type: object
properties:
Expand Down Expand Up @@ -1121,6 +1162,26 @@ definitions:
properties:
drive_id:
type: string
file:
description:
Configuration for the host-file-backed device.
If provided, overrides `path_on_host`, `rate_limiter`.
$ref: "#/definitions/PartialFileConfig"
path_on_host:
type: string
description:
Host level path for the guest drive
This parameter has been deprecated since v1.6.0.
Use parameters in `file` instead.
rate_limiter:
description:
This parameter has been deprecated since v1.6.0.
Use parameters in `file` instead.
$ref: "#/definitions/RateLimiter"

PartialFileConfig:
type: object
properties:
path_on_host:
type: string
description: Host level path for the guest drive
Expand Down Expand Up @@ -1244,6 +1305,15 @@ definitions:
description: The total number of tokens this bucket can hold.
minimum: 0

VhostUserConfig:
type: object
required:
- socket
properties:
socket:
type: string
description: Socket path for vhost-user backend.

Vm:
type: object
description:
Expand Down
12 changes: 8 additions & 4 deletions src/utils/src/vm_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,15 @@ fn build_guarded_region(

// SAFETY: Safe because the parameters are valid.
unsafe {
MmapRegionBuilder::new_with_bitmap(size, bitmap)
let builder = MmapRegionBuilder::new_with_bitmap(size, bitmap)
.with_raw_mmap_pointer(region_addr.cast::<u8>())
.with_mmap_prot(prot)
.with_mmap_flags(flags)
.build()
.with_mmap_flags(flags);

match maybe_file_offset {
Some(file_offset) => builder.with_file_offset(file_offset).build(),
None => builder.build(),
}
}
}

Expand All @@ -120,7 +124,7 @@ pub fn create_guest_memory(
for region in regions {
let flags = match region.0 {
None => libc::MAP_NORESERVE | libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
Some(_) => libc::MAP_NORESERVE | libc::MAP_PRIVATE,
Some(_) => libc::MAP_NORESERVE | libc::MAP_SHARED,
};

let mmap_region =
Expand Down
2 changes: 2 additions & 0 deletions src/vmm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ kvm-ioctls = "0.15.0"
lazy_static = "1.4.0"
libc = "0.2.117"
linux-loader = "0.9.0"
memfd = "0.6.3"
serde = { version = "1.0.136", features = ["derive"] }
semver = { version = "1.0.17", features = ["serde"] }
serde_json = "1.0.78"
Expand All @@ -27,6 +28,7 @@ displaydoc = "0.2.4"
userfaultfd = "0.6.0"
versionize = "0.1.10"
versionize_derive = "0.1.5"
vhost = { version = "0.8.1", features = ["vhost-user-master"] }
vm-allocator = "0.1.0"
vm-fdt = "0.2.0"
vm-superio = "0.7.0"
Expand Down
29 changes: 19 additions & 10 deletions src/vmm/src/arch/aarch64/fdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use utils::vm_memory::{
};
use vm_fdt::{Error as VmFdtError, FdtWriter, FdtWriterNode};

use super::super::{DeviceType, InitrdConfig};
use super::super::{DeviceSubtype, DeviceType, InitrdConfig};
use super::cache_info::{read_cache_config, CacheEntry};
use super::get_fdt_addr;
use super::gic::GICDevice;
Expand Down Expand Up @@ -67,7 +67,7 @@ pub fn create_fdt<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildHasher
guest_mem: &GuestMemoryMmap,
vcpu_mpidr: Vec<u64>,
cmdline: CString,
device_info: &HashMap<(DeviceType, String), T, S>,
device_info: &HashMap<(DeviceType, DeviceSubtype, String), T, S>,
gic_device: &GICDevice,
initrd: &Option<InitrdConfig>,
) -> Result<Vec<u8>, FdtError> {
Expand Down Expand Up @@ -390,12 +390,12 @@ fn create_rtc_node<T: DeviceInfoForFDT + Clone + Debug>(

fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::BuildHasher>(
fdt: &mut FdtWriter,
dev_info: &HashMap<(DeviceType, String), T, S>,
dev_info: &HashMap<(DeviceType, DeviceSubtype, String), T, S>,
) -> Result<(), FdtError> {
// Create one temp Vec to store all virtio devices
let mut ordered_virtio_device: Vec<&T> = Vec::new();

for ((device_type, _device_id), info) in dev_info {
for ((device_type, _device_subtype, _device_id), info) in dev_info {
match device_type {
DeviceType::BootTimer => (), // since it's not a real device
DeviceType::Rtc => create_rtc_node(fdt, info)?,
Expand Down Expand Up @@ -424,6 +424,7 @@ mod tests {
use super::*;
use crate::arch::aarch64::gic::create_gic;
use crate::arch::aarch64::{arch_memory_regions, layout};
use crate::devices::virtio::SUBTYPE_NON_VIRTIO;

const LEN: u64 = 4096;

Expand Down Expand Up @@ -459,17 +460,25 @@ mod tests {
let mem = utils::vm_memory::test_utils::create_anon_guest_memory(&regions, false)
.expect("Cannot initialize memory");

let dev_info: HashMap<(DeviceType, std::string::String), MMIODeviceInfo> = [
let dev_info: HashMap<(DeviceType, DeviceSubtype, std::string::String), MMIODeviceInfo> = [
(
(DeviceType::Serial, DeviceType::Serial.to_string()),
(
DeviceType::Serial,
SUBTYPE_NON_VIRTIO,
DeviceType::Serial.to_string(),
),
MMIODeviceInfo { addr: 0x00, irq: 1 },
),
(
(DeviceType::Virtio(1), "virtio".to_string()),
(
DeviceType::Virtio(1),
SUBTYPE_NON_VIRTIO,
"virtio".to_string(),
),
MMIODeviceInfo { addr: LEN, irq: 2 },
),
(
(DeviceType::Rtc, "rtc".to_string()),
(DeviceType::Rtc, SUBTYPE_NON_VIRTIO, "rtc".to_string()),
MMIODeviceInfo {
addr: 2 * LEN,
irq: 3,
Expand Down Expand Up @@ -512,7 +521,7 @@ mod tests {
&mem,
vec![0],
CString::new("console=tty0").unwrap(),
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
&HashMap::<(DeviceType, DeviceSubtype, std::string::String), MMIODeviceInfo>::new(),
&gic,
&None,
)
Expand Down Expand Up @@ -575,7 +584,7 @@ mod tests {
&mem,
vec![0],
CString::new("console=tty0").unwrap(),
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
&HashMap::<(DeviceType, DeviceSubtype, std::string::String), MMIODeviceInfo>::new(),
&gic,
&Some(initrd),
)
Expand Down
4 changes: 2 additions & 2 deletions src/vmm/src/arch/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use utils::vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryMmap};

pub use self::fdt::DeviceInfoForFDT;
use self::gic::GICDevice;
use crate::arch::DeviceType;
use crate::arch::{DeviceSubtype, DeviceType};

/// Errors thrown while configuring aarch64 system.
#[derive(Debug, derive_more::From)]
Expand Down Expand Up @@ -59,7 +59,7 @@ pub fn configure_system<T: DeviceInfoForFDT + Clone + Debug, S: std::hash::Build
guest_mem: &GuestMemoryMmap,
cmdline_cstring: CString,
vcpu_mpidr: Vec<u64>,
device_info: &HashMap<(DeviceType, String), T, S>,
device_info: &HashMap<(DeviceType, DeviceSubtype, String), T, S>,
gic_device: &GICDevice,
initrd: &Option<super::InitrdConfig>,
) -> Result<(), ConfigurationError> {
Expand Down
3 changes: 3 additions & 0 deletions src/vmm/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pub enum DeviceType {
BootTimer,
}

/// Subtypes for devices that can get attached to this platform.
pub type DeviceSubtype = u32;

/// Type for passing information about the initrd in the guest memory.
#[derive(Debug)]
pub struct InitrdConfig {
Expand Down
Loading
Loading