mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
block: Add support for user specified ID_SERIAL
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
This commit is contained in:
parent
49e342314d
commit
c4e8e653ac
@ -116,8 +116,8 @@ fn build_device_id(disk_path: &Path) -> result::Result<String, Error> {
|
||||
Ok(device_id)
|
||||
}
|
||||
|
||||
pub fn build_disk_image_id(disk_path: &Path) -> Vec<u8> {
|
||||
let mut default_disk_image_id = vec![0; VIRTIO_BLK_ID_BYTES as usize];
|
||||
pub fn build_serial(disk_path: &Path) -> Vec<u8> {
|
||||
let mut default_serial = vec![0; VIRTIO_BLK_ID_BYTES as usize];
|
||||
match build_device_id(disk_path) {
|
||||
Err(_) => {
|
||||
warn!("Could not generate device id. We'll use a default.");
|
||||
@ -127,10 +127,10 @@ pub fn build_disk_image_id(disk_path: &Path) -> Vec<u8> {
|
||||
// This will also zero out any leftover bytes.
|
||||
let disk_id = m.as_bytes();
|
||||
let bytes_to_copy = cmp::min(disk_id.len(), VIRTIO_BLK_ID_BYTES as usize);
|
||||
default_disk_image_id[..bytes_to_copy].clone_from_slice(&disk_id[..bytes_to_copy])
|
||||
default_serial[..bytes_to_copy].clone_from_slice(&disk_id[..bytes_to_copy])
|
||||
}
|
||||
}
|
||||
default_disk_image_id
|
||||
default_serial
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@ -330,7 +330,7 @@ impl Request {
|
||||
disk: &mut T,
|
||||
disk_nsectors: u64,
|
||||
mem: &GuestMemoryMmap,
|
||||
disk_id: &[u8],
|
||||
serial: &[u8],
|
||||
) -> result::Result<u32, ExecuteError> {
|
||||
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
||||
.map_err(ExecuteError::Seek)?;
|
||||
@ -362,10 +362,10 @@ impl Request {
|
||||
}
|
||||
RequestType::Flush => disk.flush().map_err(ExecuteError::Flush)?,
|
||||
RequestType::GetDeviceId => {
|
||||
if (*data_len as usize) < disk_id.len() {
|
||||
if (*data_len as usize) < serial.len() {
|
||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||
}
|
||||
mem.write_slice(disk_id, *data_addr)
|
||||
mem.write_slice(serial, *data_addr)
|
||||
.map_err(ExecuteError::Write)?;
|
||||
}
|
||||
RequestType::Unsupported(t) => return Err(ExecuteError::Unsupported(t)),
|
||||
@ -379,7 +379,7 @@ impl Request {
|
||||
mem: &GuestMemoryMmap,
|
||||
disk_nsectors: u64,
|
||||
disk_image: &mut dyn AsyncIo,
|
||||
disk_id: &[u8],
|
||||
serial: &[u8],
|
||||
user_data: u64,
|
||||
) -> result::Result<bool, ExecuteError> {
|
||||
let sector = self.sector;
|
||||
@ -481,10 +481,10 @@ impl Request {
|
||||
} else {
|
||||
return Err(ExecuteError::BadRequest(Error::TooManyDescriptors));
|
||||
};
|
||||
if (data_len as usize) < disk_id.len() {
|
||||
if (data_len as usize) < serial.len() {
|
||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||
}
|
||||
mem.write_slice(disk_id, data_addr)
|
||||
mem.write_slice(serial, data_addr)
|
||||
.map_err(ExecuteError::Write)?;
|
||||
return Ok(false);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ fuzz_target!(|bytes| {
|
||||
false,
|
||||
2,
|
||||
256,
|
||||
None,
|
||||
SeccompAction::Allow,
|
||||
None,
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
|
@ -9,7 +9,7 @@
|
||||
// SPDX-License-Identifier: (Apache-2.0 AND BSD-3-Clause)
|
||||
|
||||
use block::{
|
||||
build_disk_image_id,
|
||||
build_serial,
|
||||
qcow::{self, ImageType, QcowFile},
|
||||
Request, VirtioBlockConfig,
|
||||
};
|
||||
@ -90,7 +90,7 @@ impl convert::From<Error> for io::Error {
|
||||
|
||||
struct VhostUserBlkThread {
|
||||
disk_image: Arc<Mutex<dyn DiskFile>>,
|
||||
disk_image_id: Vec<u8>,
|
||||
serial: Vec<u8>,
|
||||
disk_nsectors: u64,
|
||||
event_idx: bool,
|
||||
kill_evt: EventFd,
|
||||
@ -101,14 +101,14 @@ struct VhostUserBlkThread {
|
||||
impl VhostUserBlkThread {
|
||||
fn new(
|
||||
disk_image: Arc<Mutex<dyn DiskFile>>,
|
||||
disk_image_id: Vec<u8>,
|
||||
serial: Vec<u8>,
|
||||
disk_nsectors: u64,
|
||||
writeback: Arc<AtomicBool>,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
) -> Result<Self> {
|
||||
Ok(VhostUserBlkThread {
|
||||
disk_image,
|
||||
disk_image_id,
|
||||
serial,
|
||||
disk_nsectors,
|
||||
event_idx: false,
|
||||
kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?,
|
||||
@ -137,7 +137,7 @@ impl VhostUserBlkThread {
|
||||
&mut self.disk_image.lock().unwrap().deref_mut(),
|
||||
self.disk_nsectors,
|
||||
desc_chain.memory(),
|
||||
&self.disk_image_id,
|
||||
&self.serial,
|
||||
) {
|
||||
Ok(l) => {
|
||||
len = l;
|
||||
@ -222,7 +222,7 @@ impl VhostUserBlkBackend {
|
||||
let image: File = options.open(&image_path).unwrap();
|
||||
let mut raw_img: qcow::RawFile = qcow::RawFile::new(image, direct);
|
||||
|
||||
let image_id = build_disk_image_id(&PathBuf::from(&image_path));
|
||||
let serial = build_serial(&PathBuf::from(&image_path));
|
||||
let image_type = qcow::detect_image_type(&mut raw_img).unwrap();
|
||||
let image = match image_type {
|
||||
ImageType::Raw => Arc::new(Mutex::new(raw_img)) as Arc<Mutex<dyn DiskFile>>,
|
||||
@ -250,7 +250,7 @@ impl VhostUserBlkBackend {
|
||||
for i in 0..num_queues {
|
||||
let thread = Mutex::new(VhostUserBlkThread::new(
|
||||
image.clone(),
|
||||
image_id.clone(),
|
||||
serial.clone(),
|
||||
nsectors,
|
||||
writeback.clone(),
|
||||
mem.clone(),
|
||||
|
@ -20,7 +20,7 @@ use crate::GuestMemoryMmap;
|
||||
use crate::VirtioInterrupt;
|
||||
use anyhow::anyhow;
|
||||
use block::{
|
||||
async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_disk_image_id, Request,
|
||||
async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_serial, Request,
|
||||
RequestType, VirtioBlockConfig,
|
||||
};
|
||||
use rate_limiter::{RateLimiter, TokenType};
|
||||
@ -124,7 +124,7 @@ struct BlockEpollHandler {
|
||||
disk_image: Box<dyn AsyncIo>,
|
||||
disk_nsectors: u64,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
disk_image_id: Vec<u8>,
|
||||
serial: Vec<u8>,
|
||||
kill_evt: EventFd,
|
||||
pause_evt: EventFd,
|
||||
writeback: Arc<AtomicBool>,
|
||||
@ -205,7 +205,7 @@ impl BlockEpollHandler {
|
||||
desc_chain.memory(),
|
||||
self.disk_nsectors,
|
||||
self.disk_image.as_mut(),
|
||||
&self.disk_image_id,
|
||||
&self.serial,
|
||||
desc_chain.head_index() as u64,
|
||||
)
|
||||
.map_err(Error::RequestExecuting)?
|
||||
@ -504,6 +504,7 @@ pub struct Block {
|
||||
rate_limiter_config: Option<RateLimiterConfig>,
|
||||
exit_evt: EventFd,
|
||||
read_only: bool,
|
||||
serial: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
@ -528,6 +529,7 @@ impl Block {
|
||||
iommu: bool,
|
||||
num_queues: usize,
|
||||
queue_size: u16,
|
||||
serial: Option<String>,
|
||||
seccomp_action: SeccompAction,
|
||||
rate_limiter_config: Option<RateLimiterConfig>,
|
||||
exit_evt: EventFd,
|
||||
@ -608,6 +610,8 @@ impl Block {
|
||||
(disk_nsectors, avail_features, 0, config, false)
|
||||
};
|
||||
|
||||
let serial = serial.map(Vec::from).unwrap_or(build_serial(&disk_path));
|
||||
|
||||
Ok(Block {
|
||||
common: VirtioCommon {
|
||||
device_type: VirtioDeviceType::Block as u32,
|
||||
@ -630,6 +634,7 @@ impl Block {
|
||||
rate_limiter_config,
|
||||
exit_evt,
|
||||
read_only,
|
||||
serial,
|
||||
})
|
||||
}
|
||||
|
||||
@ -726,7 +731,6 @@ impl VirtioDevice for Block {
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
|
||||
let disk_image_id = build_disk_image_id(&self.disk_path);
|
||||
self.update_writeback();
|
||||
|
||||
let mut epoll_threads = Vec::new();
|
||||
@ -754,7 +758,7 @@ impl VirtioDevice for Block {
|
||||
})?,
|
||||
disk_nsectors: self.disk_nsectors,
|
||||
interrupt_cb: interrupt_cb.clone(),
|
||||
disk_image_id: disk_image_id.clone(),
|
||||
serial: self.serial.clone(),
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
writeback: self.writeback.clone(),
|
||||
|
@ -820,6 +820,8 @@ components:
|
||||
format: int16
|
||||
id:
|
||||
type: string
|
||||
serial:
|
||||
type: string
|
||||
|
||||
NetConfig:
|
||||
type: object
|
||||
|
@ -779,7 +779,8 @@ impl DiskConfig {
|
||||
.add("ops_refill_time")
|
||||
.add("id")
|
||||
.add("_disable_io_uring")
|
||||
.add("pci_segment");
|
||||
.add("pci_segment")
|
||||
.add("serial");
|
||||
parser.parse(disk).map_err(Error::ParseDisk)?;
|
||||
|
||||
let path = parser.get("path").map(PathBuf::from);
|
||||
@ -846,6 +847,7 @@ impl DiskConfig {
|
||||
.convert("ops_refill_time")
|
||||
.map_err(Error::ParseDisk)?
|
||||
.unwrap_or_default();
|
||||
let serial = parser.get("serial");
|
||||
let bw_tb_config = if bw_size != 0 && bw_refill_time != 0 {
|
||||
Some(TokenBucketConfig {
|
||||
size: bw_size,
|
||||
@ -886,6 +888,7 @@ impl DiskConfig {
|
||||
id,
|
||||
disable_io_uring,
|
||||
pci_segment,
|
||||
serial,
|
||||
})
|
||||
}
|
||||
|
||||
@ -2462,7 +2465,14 @@ mod tests {
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
DiskConfig::parse("path=/path/to_file,serial=test")?,
|
||||
DiskConfig {
|
||||
path: Some(PathBuf::from("/path/to_file")),
|
||||
serial: Some(String::from("test")),
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -2315,6 +2315,7 @@ impl DeviceManager {
|
||||
self.force_iommu | disk_cfg.iommu,
|
||||
disk_cfg.num_queues,
|
||||
disk_cfg.queue_size,
|
||||
disk_cfg.serial.clone(),
|
||||
self.seccomp_action.clone(),
|
||||
disk_cfg.rate_limiter_config,
|
||||
self.exit_evt
|
||||
|
@ -220,6 +220,8 @@ pub struct DiskConfig {
|
||||
pub disable_io_uring: bool,
|
||||
#[serde(default)]
|
||||
pub pci_segment: u16,
|
||||
#[serde(default)]
|
||||
pub serial: Option<String>,
|
||||
}
|
||||
|
||||
pub const DEFAULT_DISK_NUM_QUEUES: usize = 1;
|
||||
@ -249,6 +251,7 @@ impl Default for DiskConfig {
|
||||
disable_io_uring: false,
|
||||
rate_limiter_config: None,
|
||||
pci_segment: 0,
|
||||
serial: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user