Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
79 changes: 48 additions & 31 deletions block/src/raw_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause

use std::fs::File;
use std::io::{Error, Seek, SeekFrom};
use std::io::Error;
use std::os::unix::io::{AsRawFd, RawFd};

use io_uring::{IoUring, opcode, types};
use libc::{FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE};
use log::warn;
use vmm_sys_util::eventfd::EventFd;

use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::{BatchRequest, DiskTopology, RequestType, SECTOR_SIZE, probe_sparse_support};
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd};
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
use crate::{BatchRequest, DiskTopology, RequestType, SECTOR_SIZE, disk_file, probe_sparse_support};

#[derive(Debug)]
pub struct RawFileDisk {
file: File,
}
Expand All @@ -26,47 +25,65 @@ impl RawFileDisk {
}
}

impl DiskFile for RawFileDisk {
fn logical_size(&mut self) -> DiskFileResult<u64> {
impl disk_file::DiskSize for RawFileDisk {
fn logical_size(&self) -> BlockResult<u64> {
self.file
.seek(SeekFrom::End(0))
.map_err(DiskFileError::Size)
.metadata()
.map(|m| m.len())
.map_err(BlockError::from)
}
}

fn physical_size(&mut self) -> DiskFileResult<u64> {
impl disk_file::PhysicalSize for RawFileDisk {
fn physical_size(&self) -> BlockResult<u64> {
self.file
.metadata()
.map(|m| m.len())
.map_err(DiskFileError::Size)
}

fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
let mut raw = RawFileAsync::new(self.file.as_raw_fd(), ring_depth)
.map_err(DiskFileError::NewAsyncIo)?;
raw.alignment =
DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size);
Ok(Box::new(raw) as Box<dyn AsyncIo>)
.map_err(BlockError::from)
}
}

fn topology(&mut self) -> DiskTopology {
if let Ok(topology) = DiskTopology::probe(&self.file) {
topology
} else {
warn!("Unable to get device topology. Using default topology");
DiskTopology::default()
}
impl disk_file::DiskFd for RawFileDisk {
fn fd(&self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}

fn resize(&mut self, size: u64) -> DiskFileResult<()> {
self.file.set_len(size).map_err(DiskFileError::ResizeError)
impl disk_file::Geometry for RawFileDisk {
fn topology(&self) -> DiskTopology {
DiskTopology::probe(&self.file).unwrap_or_default()
}
}

impl disk_file::SparseCapable for RawFileDisk {
fn supports_sparse_operations(&self) -> bool {
probe_sparse_support(&self.file)
}
}

fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
impl disk_file::Resizable for RawFileDisk {
fn resize(&mut self, size: u64) -> BlockResult<()> {
self.file.set_len(size).map_err(|e| {
BlockError::new(BlockErrorKind::Io, e)
.with_op(ErrorOp::Resize)
})
}
}

impl disk_file::DiskFile for RawFileDisk {}

impl disk_file::AsyncDiskFile for RawFileDisk {
fn try_clone(&self) -> BlockResult<Box<dyn disk_file::AsyncDiskFile>> {
let cloned = self.file.try_clone().map_err(BlockError::from)?;
Ok(Box::new(RawFileDisk::new(cloned)))
}

fn new_async_io(&self, ring_depth: u32) -> BlockResult<Box<dyn AsyncIo>> {
let mut raw = RawFileAsync::new(self.file.as_raw_fd(), ring_depth)
.map_err(BlockError::from)?;
raw.alignment =
DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size);
Ok(Box::new(raw) as Box<dyn AsyncIo>)
}
}

Expand Down
74 changes: 47 additions & 27 deletions block/src/raw_async_aio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@

use std::collections::VecDeque;
use std::fs::File;
use std::io::{Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};

use libc::{FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE};
use log::warn;
use vmm_sys_util::aio;
use vmm_sys_util::eventfd::EventFd;

use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::{DiskTopology, SECTOR_SIZE, probe_sparse_support};
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd};
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
use crate::{DiskTopology, SECTOR_SIZE, disk_file, probe_sparse_support};

#[derive(Debug)]
pub struct RawFileDiskAio {
file: File,
}
Expand All @@ -30,43 +28,65 @@ impl RawFileDiskAio {
}
}

impl DiskFile for RawFileDiskAio {
fn logical_size(&mut self) -> DiskFileResult<u64> {
impl disk_file::DiskSize for RawFileDiskAio {
fn logical_size(&self) -> BlockResult<u64> {
self.file
.seek(SeekFrom::End(0))
.map_err(DiskFileError::Size)
.metadata()
.map(|m| m.len())
.map_err(BlockError::from)
}
}

fn physical_size(&mut self) -> DiskFileResult<u64> {
impl disk_file::PhysicalSize for RawFileDiskAio {
fn physical_size(&self) -> BlockResult<u64> {
self.file
.metadata()
.map(|m| m.len())
.map_err(DiskFileError::Size)
.map_err(BlockError::from)
}
}

fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
let mut raw = RawFileAsyncAio::new(self.file.as_raw_fd(), ring_depth)
.map_err(DiskFileError::NewAsyncIo)?;
raw.alignment =
DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size);
Ok(Box::new(raw) as Box<dyn AsyncIo>)
impl disk_file::DiskFd for RawFileDiskAio {
fn fd(&self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}

fn topology(&mut self) -> DiskTopology {
if let Ok(topology) = DiskTopology::probe(&self.file) {
topology
} else {
warn!("Unable to get device topology. Using default topology");
DiskTopology::default()
}
impl disk_file::Geometry for RawFileDiskAio {
fn topology(&self) -> DiskTopology {
DiskTopology::probe(&self.file).unwrap_or_default()
}
}

impl disk_file::SparseCapable for RawFileDiskAio {
fn supports_sparse_operations(&self) -> bool {
probe_sparse_support(&self.file)
}
}

fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
impl disk_file::Resizable for RawFileDiskAio {
fn resize(&mut self, size: u64) -> BlockResult<()> {
self.file.set_len(size).map_err(|e| {
BlockError::new(BlockErrorKind::Io, e)
.with_op(ErrorOp::Resize)
})
}
}

impl disk_file::DiskFile for RawFileDiskAio {}

impl disk_file::AsyncDiskFile for RawFileDiskAio {
fn try_clone(&self) -> BlockResult<Box<dyn disk_file::AsyncDiskFile>> {
let cloned = self.file.try_clone().map_err(BlockError::from)?;
Ok(Box::new(RawFileDiskAio::new(cloned)))
}

fn new_async_io(&self, ring_depth: u32) -> BlockResult<Box<dyn AsyncIo>> {
let mut raw = RawFileAsyncAio::new(self.file.as_raw_fd(), ring_depth)
.map_err(BlockError::from)?;
raw.alignment =
DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size);
Ok(Box::new(raw) as Box<dyn AsyncIo>)
}
}

Expand Down
72 changes: 46 additions & 26 deletions block/src/raw_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@

use std::collections::VecDeque;
use std::fs::File;
use std::io::{Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};

use libc::{FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE};
use log::warn;
use vmm_sys_util::eventfd::EventFd;

use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFile, DiskFileError, DiskFileResult,
};
use crate::{DiskTopology, SECTOR_SIZE, probe_sparse_support};
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd};
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
use crate::{DiskTopology, SECTOR_SIZE, disk_file, probe_sparse_support};

#[derive(Debug)]
pub struct RawFileDiskSync {
file: File,
}
Expand All @@ -26,42 +24,64 @@ impl RawFileDiskSync {
}
}

impl DiskFile for RawFileDiskSync {
fn logical_size(&mut self) -> DiskFileResult<u64> {
impl disk_file::DiskSize for RawFileDiskSync {
fn logical_size(&self) -> BlockResult<u64> {
self.file
.seek(SeekFrom::End(0))
.map_err(DiskFileError::Size)
.metadata()
.map(|m| m.len())
.map_err(BlockError::from)
}
}

fn physical_size(&mut self) -> DiskFileResult<u64> {
impl disk_file::PhysicalSize for RawFileDiskSync {
fn physical_size(&self) -> BlockResult<u64> {
self.file
.metadata()
.map(|m| m.len())
.map_err(DiskFileError::Size)
.map_err(BlockError::from)
}
}

fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
let mut raw = RawFileSync::new(self.file.as_raw_fd());
raw.alignment =
DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size);
Ok(Box::new(raw) as Box<dyn AsyncIo>)
impl disk_file::DiskFd for RawFileDiskSync {
fn fd(&self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
}
}

fn topology(&mut self) -> DiskTopology {
if let Ok(topology) = DiskTopology::probe(&self.file) {
topology
} else {
warn!("Unable to get device topology. Using default topology");
DiskTopology::default()
}
impl disk_file::Geometry for RawFileDiskSync {
fn topology(&self) -> DiskTopology {
DiskTopology::probe(&self.file).unwrap_or_default()
}
}

impl disk_file::SparseCapable for RawFileDiskSync {
fn supports_sparse_operations(&self) -> bool {
probe_sparse_support(&self.file)
}
}

fn fd(&mut self) -> BorrowedDiskFd<'_> {
BorrowedDiskFd::new(self.file.as_raw_fd())
impl disk_file::Resizable for RawFileDiskSync {
fn resize(&mut self, size: u64) -> BlockResult<()> {
self.file.set_len(size).map_err(|e| {
BlockError::new(BlockErrorKind::Io, e)
.with_op(ErrorOp::Resize)
})
}
}

impl disk_file::DiskFile for RawFileDiskSync {}

impl disk_file::AsyncDiskFile for RawFileDiskSync {
fn try_clone(&self) -> BlockResult<Box<dyn disk_file::AsyncDiskFile>> {
let cloned = self.file.try_clone().map_err(BlockError::from)?;
Ok(Box::new(RawFileDiskSync::new(cloned)))
}

fn new_async_io(&self, _ring_depth: u32) -> BlockResult<Box<dyn AsyncIo>> {
let mut raw = RawFileSync::new(self.file.as_raw_fd());
raw.alignment =
DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size);
Ok(Box::new(raw) as Box<dyn AsyncIo>)
}
}

Expand Down
4 changes: 1 addition & 3 deletions fuzz/fuzz_targets/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::{ffi, io};

use block::async_io::DiskFile;
use block::disk_file::DiskBackend;
use block::fcntl::LockGranularityChoice;
use block::raw_sync::RawFileDiskSync;
Expand Down Expand Up @@ -53,11 +52,10 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
// Create a virtio-block device backed by a synchronous raw file
let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
let disk_file: File = unsafe { File::from_raw_fd(shm) };
let qcow_disk = Box::new(RawFileDiskSync::new(disk_file)) as Box<dyn DiskFile>;
let queue_affinity = BTreeMap::new();
let mut block = Block::new(
"tmp".to_owned(),
DiskBackend::Legacy(qcow_disk),
DiskBackend::Next(Box::new(RawFileDiskSync::new(disk_file))),
PathBuf::from(""),
false,
false,
Expand Down
10 changes: 3 additions & 7 deletions vmm/src/device_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2756,18 +2756,14 @@ impl DeviceManager {
unreachable!("Checked in if statement above");
#[cfg(feature = "io_uring")]
{
DiskBackend::Legacy(
Box::new(RawFileDisk::new(file)) as Box<dyn DiskFile>
)
DiskBackend::Next(Box::new(RawFileDisk::new(file)))
}
} else if !disk_cfg.disable_aio && self.aio_is_supported() {
info!("Using asynchronous RAW disk file (aio)");
DiskBackend::Legacy(Box::new(RawFileDiskAio::new(file)) as Box<dyn DiskFile>)
DiskBackend::Next(Box::new(RawFileDiskAio::new(file)))
} else {
info!("Using synchronous RAW disk file");
DiskBackend::Legacy(
Box::new(RawFileDiskSync::new(file)) as Box<dyn DiskFile>
)
DiskBackend::Next(Box::new(RawFileDiskSync::new(file)))
}
}
ImageType::Qcow2 => {
Expand Down
Loading