diff --git a/virtio-devices/src/block.rs b/virtio-devices/src/block.rs index 793242e28..d914d2710 100644 --- a/virtio-devices/src/block.rs +++ b/virtio-devices/src/block.rs @@ -56,6 +56,8 @@ const RATE_LIMITER_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 3; // latency scale, for reduce precision loss in calculate. const LATENCY_SCALE: u64 = 10000; +pub const MINIMUM_BLOCK_QUEUE_SIZE: u16 = 2; + #[derive(Error, Debug)] pub enum Error { #[error("Failed to parse the request: {0}")] @@ -625,6 +627,7 @@ impl Block { | (1u64 << VIRTIO_BLK_F_CONFIG_WCE) | (1u64 << VIRTIO_BLK_F_BLK_SIZE) | (1u64 << VIRTIO_BLK_F_TOPOLOGY) + | (1u64 << VIRTIO_BLK_F_SEG_MAX) | (1u64 << VIRTIO_RING_F_EVENT_IDX) | (1u64 << VIRTIO_RING_F_INDIRECT_DESC); if iommu { @@ -660,6 +663,7 @@ impl Block { physical_block_exp, min_io_size: (topology.minimum_io_size / logical_block_size) as u16, opt_io_size: (topology.optimal_io_size / logical_block_size) as u32, + seg_max: (queue_size - MINIMUM_BLOCK_QUEUE_SIZE) as u32, ..Default::default() }; diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 422e904f0..b2b9873e6 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -14,6 +14,7 @@ use option_parser::{ }; use serde::{Deserialize, Serialize}; use thiserror::Error; +use virtio_devices::block::MINIMUM_BLOCK_QUEUE_SIZE; use virtio_devices::{RateLimiterConfig, TokenBucketConfig}; use crate::landlock::LandlockAccess; @@ -168,6 +169,8 @@ pub enum ValidationError { TdxFirmwareMissing, /// Insufficient vCPUs for queues TooManyQueues, + /// Invalid queue size + InvalidQueueSize(u16), /// Need shared memory for vfio-user UserDevicesRequireSharedMemory, /// VSOCK Context Identifier has a special meaning, unsuitable for a VM. @@ -273,6 +276,12 @@ impl fmt::Display for ValidationError { TooManyQueues => { write!(f, "Number of vCPUs is insufficient for number of queues") } + InvalidQueueSize(s) => { + write!( + f, + "Queue size is smaller than {MINIMUM_BLOCK_QUEUE_SIZE}: {s}" + ) + } UserDevicesRequireSharedMemory => { write!( f, @@ -1307,6 +1316,10 @@ impl DiskConfig { return Err(ValidationError::TooManyQueues); } + if self.queue_size <= MINIMUM_BLOCK_QUEUE_SIZE { + return Err(ValidationError::InvalidQueueSize(self.queue_size)); + } + if self.vhost_user && self.iommu { return Err(ValidationError::IommuNotSupported); }