diff --git a/block_util/src/fixed_vhd.rs b/block_util/src/fixed_vhd.rs new file mode 100644 index 000000000..49f012cd8 --- /dev/null +++ b/block_util/src/fixed_vhd.rs @@ -0,0 +1,87 @@ +// Copyright © 2021 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +use crate::vhd::VhdFooter; +use std::fs::File; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::os::unix::io::{AsRawFd, RawFd}; + +#[derive(Debug)] +pub struct FixedVhd { + file: File, + size: u64, + position: u64, +} + +impl FixedVhd { + pub fn new(mut file: File) -> std::io::Result { + let footer = VhdFooter::new(&mut file)?; + + Ok(Self { + file, + size: footer.current_size(), + position: 0, + }) + } + + pub fn size(&self) -> u64 { + self.size + } +} + +impl AsRawFd for FixedVhd { + fn as_raw_fd(&self) -> RawFd { + self.file.as_raw_fd() + } +} + +impl Read for FixedVhd { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + match self.file.read(buf) { + Ok(r) => { + self.position = self.position.checked_add(r.try_into().unwrap()).unwrap(); + Ok(r) + } + Err(e) => Err(e), + } + } +} + +impl Write for FixedVhd { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + match self.file.write(buf) { + Ok(r) => { + self.position = self.position.checked_add(r.try_into().unwrap()).unwrap(); + Ok(r) + } + Err(e) => Err(e), + } + } + + fn flush(&mut self) -> std::io::Result<()> { + self.file.sync_all() + } +} + +impl Seek for FixedVhd { + fn seek(&mut self, newpos: SeekFrom) -> std::io::Result { + match self.file.seek(newpos) { + Ok(pos) => { + self.position = pos; + Ok(pos) + } + Err(e) => Err(e), + } + } +} + +impl Clone for FixedVhd { + fn clone(&self) -> Self { + Self { + file: self.file.try_clone().expect("FixedVhd cloning failed"), + size: self.size, + position: self.position, + } + } +} diff --git a/block_util/src/fixed_vhd_async.rs b/block_util/src/fixed_vhd_async.rs index 7b03d0118..ef833a849 100644 --- a/block_util/src/fixed_vhd_async.rs +++ b/block_util/src/fixed_vhd_async.rs @@ -5,36 +5,28 @@ use crate::async_io::{ AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, }; +use crate::fixed_vhd::FixedVhd; use crate::raw_async::RawFileAsync; -use crate::vhd::VhdFooter; use std::fs::File; use std::os::unix::io::{AsRawFd, RawFd}; use vmm_sys_util::eventfd::EventFd; -pub struct FixedVhdDiskAsync { - file: File, - size: u64, -} +pub struct FixedVhdDiskAsync(FixedVhd); impl FixedVhdDiskAsync { - pub fn new(mut file: File) -> std::io::Result { - let footer = VhdFooter::new(&mut file)?; - - Ok(FixedVhdDiskAsync { - file, - size: footer.current_size(), - }) + pub fn new(file: File) -> std::io::Result { + Ok(Self(FixedVhd::new(file)?)) } } impl DiskFile for FixedVhdDiskAsync { fn size(&mut self) -> DiskFileResult { - Ok(self.size) + Ok(self.0.size()) } fn new_async_io(&self, ring_depth: u32) -> DiskFileResult> { Ok(Box::new( - FixedVhdAsync::new(self.file.as_raw_fd(), ring_depth, self.size) + FixedVhdAsync::new(self.0.as_raw_fd(), ring_depth, self.0.size()) .map_err(DiskFileError::NewAsyncIo)?, ) as Box) } diff --git a/block_util/src/fixed_vhd_sync.rs b/block_util/src/fixed_vhd_sync.rs index 256bc02a9..605d22a40 100644 --- a/block_util/src/fixed_vhd_sync.rs +++ b/block_util/src/fixed_vhd_sync.rs @@ -5,36 +5,28 @@ use crate::async_io::{ AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, }; +use crate::fixed_vhd::FixedVhd; use crate::raw_sync::RawFileSync; -use crate::vhd::VhdFooter; use std::fs::File; use std::os::unix::io::{AsRawFd, RawFd}; use vmm_sys_util::eventfd::EventFd; -pub struct FixedVhdDiskSync { - file: File, - size: u64, -} +pub struct FixedVhdDiskSync(FixedVhd); impl FixedVhdDiskSync { - pub fn new(mut file: File) -> std::io::Result { - let footer = VhdFooter::new(&mut file)?; - - Ok(FixedVhdDiskSync { - file, - size: footer.current_size(), - }) + pub fn new(file: File) -> std::io::Result { + Ok(Self(FixedVhd::new(file)?)) } } impl DiskFile for FixedVhdDiskSync { fn size(&mut self) -> DiskFileResult { - Ok(self.size) + Ok(self.0.size()) } fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult> { Ok(Box::new( - FixedVhdSync::new(self.file.as_raw_fd(), self.size) + FixedVhdSync::new(self.0.as_raw_fd(), self.0.size()) .map_err(DiskFileError::NewAsyncIo)?, ) as Box) } diff --git a/block_util/src/lib.rs b/block_util/src/lib.rs index 067adbeec..cb03f314f 100644 --- a/block_util/src/lib.rs +++ b/block_util/src/lib.rs @@ -12,6 +12,7 @@ extern crate log; pub mod async_io; +pub mod fixed_vhd; #[cfg(feature = "io_uring")] /// Enabled with the `"io_uring"` feature pub mod fixed_vhd_async;