mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-05 21:15:45 +00:00
vm-virtio: Simplify virtio-blk configuration
This commit reuses the clear definition of the virtio-blk configuration structure, allowing both vhost-user-blk and virtio-blk devices to rely on it. This makes the code more readable for developers. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
8946a09afd
commit
8e48fc445f
@ -6,6 +6,7 @@ use super::handler::*;
|
|||||||
use super::vu_common_ctrl::*;
|
use super::vu_common_ctrl::*;
|
||||||
use super::Error as DeviceError;
|
use super::Error as DeviceError;
|
||||||
use super::{Error, Result};
|
use super::{Error, Result};
|
||||||
|
use crate::block::VirtioBlockConfig;
|
||||||
use crate::VirtioInterrupt;
|
use crate::VirtioInterrupt;
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use libc;
|
use libc;
|
||||||
@ -13,7 +14,6 @@ use libc::EFD_NONBLOCK;
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr::null;
|
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -25,15 +25,9 @@ use vhost_rs::vhost_user::{Master, VhostUserMaster, VhostUserMasterReqHandler};
|
|||||||
use vhost_rs::VhostBackend;
|
use vhost_rs::VhostBackend;
|
||||||
use virtio_bindings::bindings::virtio_blk::*;
|
use virtio_bindings::bindings::virtio_blk::*;
|
||||||
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
||||||
use vm_memory::GuestMemoryMmap;
|
use vm_memory::{ByteValued, GuestMemoryMmap};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
macro_rules! offset_of {
|
|
||||||
($ty:ty, $field:ident) => {
|
|
||||||
unsafe { &(*(null() as *const $ty)).$field as *const _ as usize }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SlaveReqHandler {}
|
struct SlaveReqHandler {}
|
||||||
impl VhostUserMasterReqHandler for SlaveReqHandler {}
|
impl VhostUserMasterReqHandler for SlaveReqHandler {}
|
||||||
|
|
||||||
@ -43,7 +37,7 @@ pub struct Blk {
|
|||||||
pause_evt: Option<EventFd>,
|
pause_evt: Option<EventFd>,
|
||||||
avail_features: u64,
|
avail_features: u64,
|
||||||
acked_features: u64,
|
acked_features: u64,
|
||||||
config_space: Vec<u8>,
|
config: VirtioBlockConfig,
|
||||||
queue_sizes: Vec<u16>,
|
queue_sizes: Vec<u16>,
|
||||||
queue_evts: Option<Vec<EventFd>>,
|
queue_evts: Option<Vec<EventFd>>,
|
||||||
interrupt_cb: Option<Arc<dyn VirtioInterrupt>>,
|
interrupt_cb: Option<Arc<dyn VirtioInterrupt>>,
|
||||||
@ -102,10 +96,9 @@ impl Blk {
|
|||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let config_len = mem::size_of::<virtio_blk_config>();
|
let config_len = mem::size_of::<VirtioBlockConfig>();
|
||||||
let config_space: Vec<u8> = vec![0u8; config_len as usize];
|
let config_space: Vec<u8> = vec![0u8; config_len as usize];
|
||||||
|
let (_, config_space) = vhost_user_blk
|
||||||
let (_, mut config_space) = vhost_user_blk
|
|
||||||
.get_config(
|
.get_config(
|
||||||
0,
|
0,
|
||||||
config_len as u32,
|
config_len as u32,
|
||||||
@ -113,12 +106,12 @@ impl Blk {
|
|||||||
config_space.as_slice(),
|
config_space.as_slice(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let mut config = VirtioBlockConfig::default();
|
||||||
let queue_num_offset = offset_of!(virtio_blk_config, num_queues);
|
if let Some(backend_config) = VirtioBlockConfig::from_slice(config_space.as_slice()) {
|
||||||
// Only set num_queues value(u16).
|
config = *backend_config;
|
||||||
let num_queues_slice = (vu_cfg.num_queues as u16).to_le_bytes();
|
// Only set num_queues value(u16).
|
||||||
config_space[queue_num_offset..queue_num_offset + mem::size_of::<u16>()]
|
config.num_queues = vu_cfg.num_queues as u16;
|
||||||
.copy_from_slice(&num_queues_slice);
|
}
|
||||||
|
|
||||||
Ok(Blk {
|
Ok(Blk {
|
||||||
vhost_user_blk,
|
vhost_user_blk,
|
||||||
@ -126,7 +119,7 @@ impl Blk {
|
|||||||
pause_evt: None,
|
pause_evt: None,
|
||||||
avail_features,
|
avail_features,
|
||||||
acked_features,
|
acked_features,
|
||||||
config_space,
|
config,
|
||||||
queue_sizes: vec![vu_cfg.queue_size; vu_cfg.num_queues],
|
queue_sizes: vec![vu_cfg.queue_size; vu_cfg.num_queues],
|
||||||
queue_evts: None,
|
queue_evts: None,
|
||||||
interrupt_cb: None,
|
interrupt_cb: None,
|
||||||
@ -187,34 +180,32 @@ impl VirtioDevice for Blk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_config(&self, offset: u64, mut data: &mut [u8]) {
|
fn read_config(&self, offset: u64, mut data: &mut [u8]) {
|
||||||
let config_len = self.config_space.len() as u64;
|
let config_slice = self.config.as_slice();
|
||||||
|
let config_len = config_slice.len() as u64;
|
||||||
if offset >= config_len {
|
if offset >= config_len {
|
||||||
error!("Failed to read config space");
|
error!("Failed to read config space");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(end) = offset.checked_add(data.len() as u64) {
|
if let Some(end) = offset.checked_add(data.len() as u64) {
|
||||||
// This write can't fail, offset and end are checked against config_len.
|
// This write can't fail, offset and end are checked against config_len.
|
||||||
data.write_all(&self.config_space[offset as usize..cmp::min(end, config_len) as usize])
|
data.write_all(&config_slice[offset as usize..cmp::min(end, config_len) as usize])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_config(&mut self, offset: u64, data: &[u8]) {
|
fn write_config(&mut self, offset: u64, data: &[u8]) {
|
||||||
|
let config_slice = self.config.as_mut_slice();
|
||||||
let data_len = data.len() as u64;
|
let data_len = data.len() as u64;
|
||||||
let config_len = self.config_space.len() as u64;
|
let config_len = config_slice.len() as u64;
|
||||||
if offset + data_len > config_len {
|
if offset + data_len > config_len {
|
||||||
error!("Failed to write config space");
|
error!("Failed to write config space");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// In fact, write_config() only handle wce value in vhost-user-blk.
|
|
||||||
// so, we can only set wce value here.
|
|
||||||
if self.config_space[offset as usize] == data[0] {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.vhost_user_blk
|
self.vhost_user_blk
|
||||||
.set_config(offset as u32, VhostUserConfigFlags::WRITABLE, data)
|
.set_config(offset as u32, VhostUserConfigFlags::WRITABLE, data)
|
||||||
.expect("Failed to set config");
|
.expect("Failed to set config");
|
||||||
self.config_space[offset as usize] = data[0];
|
let (_, right) = config_slice.split_at_mut(offset as usize);
|
||||||
|
right.copy_from_slice(&data[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(
|
fn activate(
|
||||||
|
Loading…
Reference in New Issue
Block a user