mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-08 22:05:20 +00:00
block_util: Factorize common code for synchronous implementations
Since QCOW and RAW synchronous implementation are very close, it makes sense to introduce some common functions that can be shared between these two. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
f6c8e4b045
commit
060df69f07
@ -18,21 +18,21 @@ pub mod qcow_sync;
|
||||
pub mod raw_async;
|
||||
pub mod raw_sync;
|
||||
|
||||
use crate::async_io::{AsyncIo, AsyncIoError};
|
||||
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, DiskFileError, DiskFileResult};
|
||||
#[cfg(feature = "io_uring")]
|
||||
use io_uring::{opcode, IoUring, Probe};
|
||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||
use std::cmp;
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||
use std::os::linux::fs::MetadataExt;
|
||||
#[cfg(feature = "io_uring")]
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use virtio_bindings::bindings::virtio_blk::*;
|
||||
use vm_memory::{ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
||||
use vm_virtio::DescriptorChain;
|
||||
#[cfg(feature = "io_uring")]
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const SECTOR_SHIFT: u8 = 9;
|
||||
@ -542,3 +542,113 @@ pub fn block_io_uring_is_supported() -> bool {
|
||||
pub fn block_io_uring_is_supported() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn disk_size(file: &mut dyn Seek, semaphore: &mut Arc<Mutex<()>>) -> DiskFileResult<u64> {
|
||||
// Take the semaphore to ensure other threads are not interacting with
|
||||
// the underlying file.
|
||||
let _lock = semaphore.lock().unwrap();
|
||||
|
||||
Ok(file.seek(SeekFrom::End(0)).map_err(DiskFileError::Size)? as u64)
|
||||
}
|
||||
|
||||
pub trait ReadSeekFile: Read + Seek {}
|
||||
impl<F: Read + Seek> ReadSeekFile for F {}
|
||||
|
||||
pub fn read_vectored_sync(
|
||||
offset: libc::off_t,
|
||||
iovecs: Vec<libc::iovec>,
|
||||
user_data: u64,
|
||||
file: &mut dyn ReadSeekFile,
|
||||
eventfd: &EventFd,
|
||||
completion_list: &mut Vec<(u64, i32)>,
|
||||
semaphore: &mut Arc<Mutex<()>>,
|
||||
) -> AsyncIoResult<()> {
|
||||
// Convert libc::iovec into IoSliceMut
|
||||
let mut slices = Vec::new();
|
||||
for iovec in iovecs.iter() {
|
||||
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
}
|
||||
|
||||
let result = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = semaphore.lock().unwrap();
|
||||
|
||||
// Move the cursor to the right offset
|
||||
file.seek(SeekFrom::Start(offset as u64))
|
||||
.map_err(AsyncIoError::ReadVectored)?;
|
||||
|
||||
// Read vectored
|
||||
file.read_vectored(slices.as_mut_slice())
|
||||
.map_err(AsyncIoError::ReadVectored)?
|
||||
};
|
||||
|
||||
completion_list.push((user_data, result as i32));
|
||||
eventfd.write(1).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub trait WriteSeekFile: Write + Seek {}
|
||||
impl<F: Write + Seek> WriteSeekFile for F {}
|
||||
|
||||
pub fn write_vectored_sync(
|
||||
offset: libc::off_t,
|
||||
iovecs: Vec<libc::iovec>,
|
||||
user_data: u64,
|
||||
file: &mut dyn WriteSeekFile,
|
||||
eventfd: &EventFd,
|
||||
completion_list: &mut Vec<(u64, i32)>,
|
||||
semaphore: &mut Arc<Mutex<()>>,
|
||||
) -> AsyncIoResult<()> {
|
||||
// Convert libc::iovec into IoSlice
|
||||
let mut slices = Vec::new();
|
||||
for iovec in iovecs.iter() {
|
||||
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
}
|
||||
|
||||
let result = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = semaphore.lock().unwrap();
|
||||
|
||||
// Move the cursor to the right offset
|
||||
file.seek(SeekFrom::Start(offset as u64))
|
||||
.map_err(AsyncIoError::WriteVectored)?;
|
||||
|
||||
// Write vectored
|
||||
file.write_vectored(slices.as_slice())
|
||||
.map_err(AsyncIoError::WriteVectored)?
|
||||
};
|
||||
|
||||
completion_list.push((user_data, result as i32));
|
||||
eventfd.write(1).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fsync_sync(
|
||||
user_data: Option<u64>,
|
||||
file: &mut dyn Write,
|
||||
eventfd: &EventFd,
|
||||
completion_list: &mut Vec<(u64, i32)>,
|
||||
semaphore: &mut Arc<Mutex<()>>,
|
||||
) -> AsyncIoResult<()> {
|
||||
let result: i32 = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = semaphore.lock().unwrap();
|
||||
|
||||
// Flush
|
||||
file.flush().map_err(AsyncIoError::Fsync)?;
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
if let Some(user_data) = user_data {
|
||||
completion_list.push((user_data, result));
|
||||
eventfd.write(1).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2,12 +2,10 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use crate::async_io::{
|
||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
||||
};
|
||||
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileResult};
|
||||
use crate::{disk_size, fsync_sync, read_vectored_sync, write_vectored_sync};
|
||||
use qcow::{QcowFile, RawFile};
|
||||
use std::fs::File;
|
||||
use std::io::{IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
@ -28,14 +26,7 @@ impl QcowDiskSync {
|
||||
|
||||
impl DiskFile for QcowDiskSync {
|
||||
fn size(&mut self) -> DiskFileResult<u64> {
|
||||
// Take the semaphore to ensure other threads are not interacting with
|
||||
// the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
Ok(self
|
||||
.qcow_file
|
||||
.seek(SeekFrom::End(0))
|
||||
.map_err(DiskFileError::Size)? as u64)
|
||||
disk_size(&mut self.qcow_file, &mut self.semaphore)
|
||||
}
|
||||
|
||||
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
||||
@ -76,32 +67,15 @@ impl AsyncIo for QcowSync {
|
||||
iovecs: Vec<libc::iovec>,
|
||||
user_data: u64,
|
||||
) -> AsyncIoResult<()> {
|
||||
// Convert libc::iovec into IoSliceMut
|
||||
let mut slices = Vec::new();
|
||||
for iovec in iovecs.iter() {
|
||||
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
}
|
||||
|
||||
let result = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
// Move the cursor to the right offset
|
||||
self.qcow_file
|
||||
.seek(SeekFrom::Start(offset as u64))
|
||||
.map_err(AsyncIoError::ReadVectored)?;
|
||||
|
||||
// Read vectored
|
||||
self.qcow_file
|
||||
.read_vectored(slices.as_mut_slice())
|
||||
.map_err(AsyncIoError::ReadVectored)?
|
||||
};
|
||||
|
||||
self.completion_list.push((user_data, result as i32));
|
||||
self.eventfd.write(1).unwrap();
|
||||
|
||||
Ok(())
|
||||
read_vectored_sync(
|
||||
offset,
|
||||
iovecs,
|
||||
user_data,
|
||||
&mut self.qcow_file,
|
||||
&self.eventfd,
|
||||
&mut self.completion_list,
|
||||
&mut self.semaphore,
|
||||
)
|
||||
}
|
||||
|
||||
fn write_vectored(
|
||||
@ -110,52 +84,25 @@ impl AsyncIo for QcowSync {
|
||||
iovecs: Vec<libc::iovec>,
|
||||
user_data: u64,
|
||||
) -> AsyncIoResult<()> {
|
||||
// Convert libc::iovec into IoSlice
|
||||
let mut slices = Vec::new();
|
||||
for iovec in iovecs.iter() {
|
||||
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
}
|
||||
|
||||
let result = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
// Move the cursor to the right offset
|
||||
self.qcow_file
|
||||
.seek(SeekFrom::Start(offset as u64))
|
||||
.map_err(AsyncIoError::WriteVectored)?;
|
||||
|
||||
// Write vectored
|
||||
self.qcow_file
|
||||
.write_vectored(slices.as_slice())
|
||||
.map_err(AsyncIoError::WriteVectored)?
|
||||
};
|
||||
|
||||
self.completion_list.push((user_data, result as i32));
|
||||
self.eventfd.write(1).unwrap();
|
||||
|
||||
Ok(())
|
||||
write_vectored_sync(
|
||||
offset,
|
||||
iovecs,
|
||||
user_data,
|
||||
&mut self.qcow_file,
|
||||
&self.eventfd,
|
||||
&mut self.completion_list,
|
||||
&mut self.semaphore,
|
||||
)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
||||
let result: i32 = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
// Flush
|
||||
self.qcow_file.flush().map_err(AsyncIoError::Fsync)?;
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
if let Some(user_data) = user_data {
|
||||
self.completion_list.push((user_data, result));
|
||||
self.eventfd.write(1).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fsync_sync(
|
||||
user_data,
|
||||
&mut self.qcow_file,
|
||||
&self.eventfd,
|
||||
&mut self.completion_list,
|
||||
&mut self.semaphore,
|
||||
)
|
||||
}
|
||||
|
||||
fn complete(&mut self) -> Vec<(u64, i32)> {
|
||||
|
@ -2,12 +2,10 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use crate::async_io::{
|
||||
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
|
||||
};
|
||||
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileResult};
|
||||
use crate::{disk_size, fsync_sync, read_vectored_sync, write_vectored_sync};
|
||||
use qcow::RawFile;
|
||||
use std::fs::File;
|
||||
use std::io::{IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
@ -27,14 +25,7 @@ impl RawFileDiskSync {
|
||||
|
||||
impl DiskFile for RawFileDiskSync {
|
||||
fn size(&mut self) -> DiskFileResult<u64> {
|
||||
// Take the semaphore to ensure other threads are not interacting with
|
||||
// the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
Ok(self
|
||||
.raw_file
|
||||
.seek(SeekFrom::End(0))
|
||||
.map_err(DiskFileError::Size)? as u64)
|
||||
disk_size(&mut self.raw_file, &mut self.semaphore)
|
||||
}
|
||||
|
||||
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
|
||||
@ -74,32 +65,15 @@ impl AsyncIo for RawFileSync {
|
||||
iovecs: Vec<libc::iovec>,
|
||||
user_data: u64,
|
||||
) -> AsyncIoResult<()> {
|
||||
// Convert libc::iovec into IoSliceMut
|
||||
let mut slices = Vec::new();
|
||||
for iovec in iovecs.iter() {
|
||||
slices.push(IoSliceMut::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
}
|
||||
|
||||
let result = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
// Move the cursor to the right offset
|
||||
self.raw_file
|
||||
.seek(SeekFrom::Start(offset as u64))
|
||||
.map_err(AsyncIoError::ReadVectored)?;
|
||||
|
||||
// Read vectored
|
||||
self.raw_file
|
||||
.read_vectored(slices.as_mut_slice())
|
||||
.map_err(AsyncIoError::ReadVectored)?
|
||||
};
|
||||
|
||||
self.completion_list.push((user_data, result as i32));
|
||||
self.eventfd.write(1).unwrap();
|
||||
|
||||
Ok(())
|
||||
read_vectored_sync(
|
||||
offset,
|
||||
iovecs,
|
||||
user_data,
|
||||
&mut self.raw_file,
|
||||
&self.eventfd,
|
||||
&mut self.completion_list,
|
||||
&mut self.semaphore,
|
||||
)
|
||||
}
|
||||
|
||||
fn write_vectored(
|
||||
@ -108,52 +82,25 @@ impl AsyncIo for RawFileSync {
|
||||
iovecs: Vec<libc::iovec>,
|
||||
user_data: u64,
|
||||
) -> AsyncIoResult<()> {
|
||||
// Convert libc::iovec into IoSlice
|
||||
let mut slices = Vec::new();
|
||||
for iovec in iovecs.iter() {
|
||||
slices.push(IoSlice::new(unsafe { std::mem::transmute(*iovec) }));
|
||||
}
|
||||
|
||||
let result = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
// Move the cursor to the right offset
|
||||
self.raw_file
|
||||
.seek(SeekFrom::Start(offset as u64))
|
||||
.map_err(AsyncIoError::WriteVectored)?;
|
||||
|
||||
// Write vectored
|
||||
self.raw_file
|
||||
.write_vectored(slices.as_slice())
|
||||
.map_err(AsyncIoError::WriteVectored)?
|
||||
};
|
||||
|
||||
self.completion_list.push((user_data, result as i32));
|
||||
self.eventfd.write(1).unwrap();
|
||||
|
||||
Ok(())
|
||||
write_vectored_sync(
|
||||
offset,
|
||||
iovecs,
|
||||
user_data,
|
||||
&mut self.raw_file,
|
||||
&self.eventfd,
|
||||
&mut self.completion_list,
|
||||
&mut self.semaphore,
|
||||
)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
||||
let result: i32 = {
|
||||
// Take the semaphore to ensure other threads are not interacting
|
||||
// with the underlying file.
|
||||
let _lock = self.semaphore.lock().unwrap();
|
||||
|
||||
// Flush
|
||||
self.raw_file.flush().map_err(AsyncIoError::Fsync)?;
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
if let Some(user_data) = user_data {
|
||||
self.completion_list.push((user_data, result));
|
||||
self.eventfd.write(1).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fsync_sync(
|
||||
user_data,
|
||||
&mut self.raw_file,
|
||||
&self.eventfd,
|
||||
&mut self.completion_list,
|
||||
&mut self.semaphore,
|
||||
)
|
||||
}
|
||||
|
||||
fn complete(&mut self) -> Vec<(u64, i32)> {
|
||||
|
Loading…
Reference in New Issue
Block a user