From 0e5721e7c464a88d0fe808a220dbc757e0098774 Mon Sep 17 00:00:00 2001 From: "yansong.ys" Date: Fri, 15 May 2026 11:31:09 +0000 Subject: [PATCH] storage: remove unnecessary vmm related crates To keep the storage crate tidy. Signed-off-by: yansong.ys --- Cargo.lock | 4 +- rafs/src/fs.rs | 73 +++++++++++++++++++- rafs/src/prefetch.rs | 2 +- storage/Cargo.toml | 4 +- storage/src/backend/localdisk.rs | 2 +- storage/src/backend/localfs.rs | 5 +- storage/src/backend/mod.rs | 2 +- storage/src/cache/cachedfile.rs | 6 +- storage/src/cache/dedup/db.rs | 3 +- storage/src/cache/dedup/mod.rs | 4 +- storage/src/cache/dummycache.rs | 5 +- storage/src/cache/filecache/mod.rs | 8 +-- storage/src/cache/mod.rs | 2 +- storage/src/cache/state/blob_state_map.rs | 4 +- storage/src/cache/state/indexed_chunk_map.rs | 4 +- storage/src/cache/state/range_map.rs | 3 +- storage/src/cache/worker.rs | 3 +- storage/src/device.rs | 38 ++-------- storage/src/lib.rs | 3 +- storage/src/meta/chunk_info_v1.rs | 3 +- storage/src/meta/toc.rs | 3 +- storage/src/remote/connection.rs | 6 +- storage/src/remote/server.rs | 3 +- storage/src/test.rs | 18 +++++ storage/src/utils.rs | 22 +++--- storage/src/volatile.rs | 67 ++++++++++++++++++ 26 files changed, 217 insertions(+), 80 deletions(-) create mode 100644 storage/src/volatile.rs diff --git a/Cargo.lock b/Cargo.lock index 6b3c024714a..b0009932bac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3048,7 +3048,6 @@ dependencies = [ "base64 0.21.7", "bitflags 1.3.2", "dragonfly-client-util", - "fuse-backend-rs", "futures", "gpt", "hex", @@ -3079,12 +3078,11 @@ dependencies = [ "sha1", "sha2", "tar", + "tempfile", "time", "tokio", "toml", "url", - "vm-memory", - "vmm-sys-util 0.15.0", ] [[package]] diff --git a/rafs/src/fs.rs b/rafs/src/fs.rs index 831dae3c9fb..d86bb260717 100644 --- a/rafs/src/fs.rs +++ b/rafs/src/fs.rs @@ -17,7 +17,7 @@ use std::any::Any; use std::cmp; use std::ffi::{CStr, OsStr, OsString}; -use std::io::Result; +use std::io::{self, Result}; use std::ops::Deref; use std::os::unix::ffi::OsStrExt; use std::path::{Path, PathBuf}; @@ -28,10 +28,13 @@ use fuse_backend_rs::abi::fuse_abi::Attr; use fuse_backend_rs::abi::fuse_abi::{stat64, statvfs64}; use fuse_backend_rs::api::filesystem::*; use fuse_backend_rs::api::BackendFileSystem; +use fuse_backend_rs::file_buf::FileVolatileSlice; +use fuse_backend_rs::file_traits::FileReadWriteVolatile; use nix::unistd::{getegid, geteuid}; use nydus_api::ConfigV2; use nydus_storage::device::{BlobDevice, BlobIoVec, BlobPrefetchRequest}; +use nydus_storage::volatile::{BlobIoRead, BlobIoWrite, VolatileSlice}; use nydus_storage::{RAFS_DEFAULT_CHUNK_SIZE, RAFS_MAX_CHUNK_SIZE}; use nydus_utils::{ div_round_up, @@ -44,6 +47,71 @@ use crate::metadata::{ use crate::prefetch::BlobPrefetcher; use crate::{RafsError, RafsIoReader, RafsResult}; +struct StorageBlobWriter<'a> { + inner: &'a mut dyn ZeroCopyWriter, +} + +struct StorageBlobReader<'a> { + inner: &'a mut dyn BlobIoRead, +} + +impl BlobIoWrite for StorageBlobWriter<'_> { + fn write_from( + &mut self, + reader: &mut dyn BlobIoRead, + size: usize, + offset: u64, + ) -> io::Result { + let mut adapter = StorageBlobReader { inner: reader }; + self.inner.write_from(&mut adapter, size, offset) + } +} + +impl FileReadWriteVolatile for StorageBlobReader<'_> { + fn read_volatile( + &mut self, + _slice: FileVolatileSlice, + ) -> std::result::Result { + unimplemented!() + } + + fn write_volatile( + &mut self, + _slice: FileVolatileSlice, + ) -> std::result::Result { + unimplemented!() + } + + fn read_at_volatile( + &mut self, + slice: FileVolatileSlice, + offset: u64, + ) -> std::result::Result { + let slice = unsafe { VolatileSlice::from_raw_ptr(slice.as_ptr(), slice.len()) }; + self.inner.read_at_volatile(slice, offset) + } + + fn read_vectored_at_volatile( + &mut self, + buffers: &[FileVolatileSlice], + offset: u64, + ) -> std::result::Result { + let buffers: Vec = buffers + .iter() + .map(|slice| unsafe { VolatileSlice::from_raw_ptr(slice.as_ptr(), slice.len()) }) + .collect(); + self.inner.read_vectored_at_volatile(&buffers, offset) + } + + fn write_at_volatile( + &mut self, + _slice: FileVolatileSlice, + _offset: u64, + ) -> std::result::Result { + unimplemented!() + } +} + /// Type of RAFS fuse handle. pub type Handle = u64; @@ -741,7 +809,8 @@ impl FileSystem for Rafs { assert_ne!(io_vec.size(), 0); // Avoid copying `desc` - let r = self.device.read_to(w, io_vec)?; + let mut storage_writer = StorageBlobWriter { inner: w }; + let r = self.device.read_to(&mut storage_writer, io_vec)?; result += r; recorder.mark_success(r); if r as u64 != io_vec.size() { diff --git a/rafs/src/prefetch.rs b/rafs/src/prefetch.rs index 15cd5f7582d..b551dd40ba6 100644 --- a/rafs/src/prefetch.rs +++ b/rafs/src/prefetch.rs @@ -573,13 +573,13 @@ impl BlobPrefetcher { mod tests { use std::io::Read; - use fuse_backend_rs::file_buf::FileVolatileSlice; use nydus_storage::backend::{BackendContext, BackendResult, BlobReader}; use nydus_storage::cache::state::ChunkMap; use nydus_storage::cache::BlobCache; use nydus_storage::device::{ BlobChunkInfo, BlobInfo, BlobIoDesc, BlobIoVec, BlobPrefetchRequest, }; + use nydus_storage::volatile::VolatileSlice as FileVolatileSlice; use nydus_storage::{StorageError, StorageResult}; use nydus_utils::crypt::{Cipher, CipherContext}; use nydus_utils::metrics::BackendMetrics; diff --git a/storage/Cargo.toml b/storage/Cargo.toml index b4f0c32815f..ecab2b27b9d 100644 --- a/storage/Cargo.toml +++ b/storage/Cargo.toml @@ -47,8 +47,6 @@ tokio = { version = "1.19.0", features = [ "time", ] } url = { version = "2.1.1", optional = true } -vm-memory = { workspace = true } -fuse-backend-rs = { workspace = true } gpt = { version = "3.1.0", optional = true } nydus-api = { version = "0.4.1", path = "../api" } @@ -64,7 +62,7 @@ rand = { version = "0.8" } futures = "0.3" http = "1.4.0" hyper-util = { version = "0.1.19", features = ["server"] } -vmm-sys-util = { workspace = true } +tempfile = "3" tar = "0.4.40" regex = "1.7.0" toml = "0.5" diff --git a/storage/src/backend/localdisk.rs b/storage/src/backend/localdisk.rs index 40f41550192..ecb8d6a3c3b 100644 --- a/storage/src/backend/localdisk.rs +++ b/storage/src/backend/localdisk.rs @@ -12,13 +12,13 @@ use std::os::unix::io::AsRawFd; use std::path::Path; use std::sync::{Arc, RwLock}; -use fuse_backend_rs::file_buf::FileVolatileSlice; use nix::sys::uio; use nydus_api::LocalDiskConfig; use nydus_utils::metrics::BackendMetrics; use crate::backend::{BackendError, BackendResult, BlobBackend, BlobReader}; use crate::utils::{readv, MemSliceCursor}; +use crate::volatile::VolatileSlice as FileVolatileSlice; type LocalDiskResult = std::result::Result; diff --git a/storage/src/backend/localfs.rs b/storage/src/backend/localfs.rs index 5b78aa8d2eb..da0fbe9cfb3 100644 --- a/storage/src/backend/localfs.rs +++ b/storage/src/backend/localfs.rs @@ -12,7 +12,6 @@ use std::os::unix::io::AsRawFd; use std::path::{Path, PathBuf}; use std::sync::{Arc, RwLock}; -use fuse_backend_rs::file_buf::FileVolatileSlice; use nix::sys::uio; use nydus_api::LocalFsConfig; @@ -20,6 +19,7 @@ use nydus_utils::metrics::BackendMetrics; use crate::backend::{BackendError, BackendResult, BlobBackend, BlobReader}; use crate::utils::{readv, MemSliceCursor}; +use crate::volatile::VolatileSlice as FileVolatileSlice; type LocalFsResult = std::result::Result; @@ -215,10 +215,11 @@ impl Drop for LocalFs { #[cfg(test)] mod tests { use super::*; + use crate::test::TempPath; use std::fs; use std::io::Write; use std::os::unix::io::{FromRawFd, IntoRawFd}; - use vmm_sys_util::{tempdir::TempDir, tempfile::TempFile}; + use tempfile::{NamedTempFile as TempFile, TempDir}; fn new_localfs( dir: &Path, diff --git a/storage/src/backend/mod.rs b/storage/src/backend/mod.rs index fac17585764..59bbc1be7ee 100644 --- a/storage/src/backend/mod.rs +++ b/storage/src/backend/mod.rs @@ -20,10 +20,10 @@ use std::thread::sleep; use std::time::SystemTime; use std::{sync::Arc, time::Duration}; -use fuse_backend_rs::file_buf::FileVolatileSlice; use nydus_utils::metrics::{BackendMetrics, ERROR_HOLDER}; use crate::utils::{alloc_buf, copyv}; +use crate::volatile::VolatileSlice as FileVolatileSlice; use crate::StorageError; #[cfg(any( diff --git a/storage/src/cache/cachedfile.rs b/storage/src/cache/cachedfile.rs index fa4af42e5e1..1fdfab24f67 100644 --- a/storage/src/cache/cachedfile.rs +++ b/storage/src/cache/cachedfile.rs @@ -20,7 +20,6 @@ use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::sync::{Arc, Mutex}; use std::time::Duration; -use fuse_backend_rs::file_buf::FileVolatileSlice; use nix::sys::uio; use nydus_utils::compress::Decoder; use nydus_utils::crypt::{self, Cipher, CipherContext}; @@ -28,6 +27,8 @@ use nydus_utils::metrics::{BlobcacheMetrics, Metric}; use nydus_utils::{compress, digest, round_up_usize, DelayType, Delayer, FileRangeReader}; use tokio::runtime::Runtime; +use crate::volatile::VolatileSlice as FileVolatileSlice; + use crate::backend::BlobReader; use crate::cache::state::ChunkMap; use crate::cache::worker::{AsyncPrefetchConfig, AsyncPrefetchMessage, AsyncWorkerMgr}; @@ -2121,8 +2122,9 @@ mod tests { #[test] fn test_entries_count_metric_increment() { use crate::cache::state::{BlobStateMap, IndexedChunkMap}; + use crate::test::TempPath; use std::sync::Arc; - use vmm_sys_util::tempdir::TempDir; + use tempfile::TempDir; // Create temporary directory and metrics let tmpdir = TempDir::new().unwrap(); diff --git a/storage/src/cache/dedup/db.rs b/storage/src/cache/dedup/db.rs index 9a9d67a68b1..94ded825398 100644 --- a/storage/src/cache/dedup/db.rs +++ b/storage/src/cache/dedup/db.rs @@ -227,7 +227,8 @@ impl CasDb { #[cfg(test)] mod tests { use super::*; - use vmm_sys_util::tempdir::TempDir; + use crate::test::TempPath; + use tempfile::TempDir; #[test] fn test_cas_blob() { diff --git a/storage/src/cache/dedup/mod.rs b/storage/src/cache/dedup/mod.rs index 251c29a19d9..9e3a5854e8e 100644 --- a/storage/src/cache/dedup/mod.rs +++ b/storage/src/cache/dedup/mod.rs @@ -222,10 +222,10 @@ impl CasMgr { mod tests { use super::*; use crate::device::BlobFeatures; - use crate::test::MockChunkInfo; + use crate::test::{MockChunkInfo, TempPath}; use crate::RAFS_DEFAULT_CHUNK_SIZE; use std::io::{Read, Seek, SeekFrom, Write}; - use vmm_sys_util::tempfile::TempFile; + use tempfile::NamedTempFile as TempFile; #[test] fn test_cas_error_display() { diff --git a/storage/src/cache/dummycache.rs b/storage/src/cache/dummycache.rs index 0765fce5104..57d64923025 100644 --- a/storage/src/cache/dummycache.rs +++ b/storage/src/cache/dummycache.rs @@ -22,7 +22,6 @@ use std::io::Result; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use fuse_backend_rs::file_buf::FileVolatileSlice; use nydus_api::CacheConfigV2; use nydus_utils::crypt::{Algorithm, Cipher, CipherContext}; use nydus_utils::{compress, digest}; @@ -34,6 +33,7 @@ use crate::device::{ BlobChunkInfo, BlobFeatures, BlobInfo, BlobIoDesc, BlobIoVec, BlobPrefetchRequest, }; use crate::utils::{alloc_buf, copyv}; +use crate::volatile::VolatileSlice as FileVolatileSlice; use crate::{StorageError, StorageResult}; struct DummyCache { @@ -250,9 +250,10 @@ impl Drop for DummyCacheMgr { mod tests { use std::fs::OpenOptions; + use crate::test::TempPath; use nydus_api::ConfigV2; use nydus_utils::metrics::BackendMetrics; - use vmm_sys_util::tempdir::TempDir; + use tempfile::TempDir; use crate::{ cache::state::IndexedChunkMap, diff --git a/storage/src/cache/filecache/mod.rs b/storage/src/cache/filecache/mod.rs index c41c5affc82..430638f0ecf 100644 --- a/storage/src/cache/filecache/mod.rs +++ b/storage/src/cache/filecache/mod.rs @@ -406,9 +406,9 @@ impl FileCacheEntry { #[cfg(test)] pub mod blob_cache_tests { + use crate::test::TempPath; use nydus_api::FileCacheConfig; - use vmm_sys_util::tempdir::TempDir; - use vmm_sys_util::tempfile::TempFile; + use tempfile::{NamedTempFile as TempFile, TempDir}; #[test] fn test_blob_cache_config() { @@ -908,10 +908,10 @@ mod tests { #[test] fn test_filecache_config_work_dir_file_path_is_invalid() { use nydus_api::FileCacheConfig; - use vmm_sys_util::tempfile::TempFile; + use tempfile::NamedTempFile as TempFile; let tmp_file = TempFile::new().unwrap(); - let file_path = tmp_file.as_path().to_path_buf(); + let file_path = tmp_file.path().to_path_buf(); let config = FileCacheConfig { work_dir: file_path.to_str().unwrap().to_owned(), ..Default::default() diff --git a/storage/src/cache/mod.rs b/storage/src/cache/mod.rs index 5918cc82872..435fb1a634e 100644 --- a/storage/src/cache/mod.rs +++ b/storage/src/cache/mod.rs @@ -21,7 +21,6 @@ use std::io::Result; use std::sync::Arc; use std::time::Instant; -use fuse_backend_rs::file_buf::FileVolatileSlice; use nydus_utils::compress::zlib_random::ZranDecoder; use nydus_utils::crypt::{self, Cipher, CipherContext}; use nydus_utils::{compress, digest}; @@ -33,6 +32,7 @@ use crate::device::{ }; use crate::meta::BlobCompressionContextInfo; use crate::utils::{alloc_buf, check_crc, check_hash}; +use crate::volatile::VolatileSlice as FileVolatileSlice; use crate::{StorageResult, RAFS_MAX_CHUNK_SIZE}; mod cachedfile; diff --git a/storage/src/cache/state/blob_state_map.rs b/storage/src/cache/state/blob_state_map.rs index 97611721e44..fe1ecf1ee85 100644 --- a/storage/src/cache/state/blob_state_map.rs +++ b/storage/src/cache/state/blob_state_map.rs @@ -372,10 +372,10 @@ pub(crate) mod tests { use std::thread; use std::time::Instant; + use crate::test::TempPath; use nydus_utils::digest::Algorithm::Blake3; use nydus_utils::digest::{Algorithm, RafsDigest}; - use vmm_sys_util::tempdir::TempDir; - use vmm_sys_util::tempfile::TempFile; + use tempfile::{NamedTempFile as TempFile, TempDir}; use super::*; use crate::cache::state::DigestedChunkMap; diff --git a/storage/src/cache/state/indexed_chunk_map.rs b/storage/src/cache/state/indexed_chunk_map.rs index 9966818a6bc..be373dd7ad0 100644 --- a/storage/src/cache/state/indexed_chunk_map.rs +++ b/storage/src/cache/state/indexed_chunk_map.rs @@ -138,12 +138,12 @@ mod tests { use std::fs::OpenOptions; use std::io::Write; use std::sync::atomic::Ordering; - use vmm_sys_util::tempdir::TempDir; + use tempfile::TempDir; use super::super::persist_map::*; use super::*; use crate::device::v5::BlobV5ChunkInfo; - use crate::test::MockChunkInfo; + use crate::test::{MockChunkInfo, TempPath}; #[test] fn test_indexed_new_invalid_file_size() { diff --git a/storage/src/cache/state/range_map.rs b/storage/src/cache/state/range_map.rs index 131bc15eeae..9d15d588f09 100644 --- a/storage/src/cache/state/range_map.rs +++ b/storage/src/cache/state/range_map.rs @@ -121,7 +121,8 @@ mod tests { use std::thread; use std::time::Instant; - use vmm_sys_util::tempdir::TempDir; + use crate::test::TempPath; + use tempfile::TempDir; use super::super::BlobStateMap; use super::*; diff --git a/storage/src/cache/worker.rs b/storage/src/cache/worker.rs index f849a8144f0..40219411976 100644 --- a/storage/src/cache/worker.rs +++ b/storage/src/cache/worker.rs @@ -424,7 +424,8 @@ impl AsyncWorkerMgr { #[cfg(test)] mod tests { use super::*; - use vmm_sys_util::tempdir::TempDir; + use crate::test::TempPath; + use tempfile::TempDir; #[test] fn test_worker_mgr_new() { diff --git a/storage/src/device.rs b/storage/src/device.rs index 8834ad8a67b..e34bfa226ff 100644 --- a/storage/src/device.rs +++ b/storage/src/device.rs @@ -32,10 +32,8 @@ use std::path::Path; use std::sync::{Arc, Mutex}; use arc_swap::ArcSwap; -use fuse_backend_rs::api::filesystem::ZeroCopyWriter; -use fuse_backend_rs::file_buf::FileVolatileSlice; -use fuse_backend_rs::file_traits::FileReadWriteVolatile; +use crate::volatile::{BlobIoRead, BlobIoWrite, VolatileSlice}; use nydus_api::ConfigV2; use nydus_utils::compress; use nydus_utils::crypt::{self, Cipher, CipherContext}; @@ -1239,7 +1237,7 @@ impl BlobDevice { } /// Read a range of data from a data blob into the provided writer - pub fn read_to(&self, w: &mut dyn ZeroCopyWriter, desc: &mut BlobIoVec) -> io::Result { + pub fn read_to(&self, w: &mut dyn BlobIoWrite, desc: &mut BlobIoVec) -> io::Result { // Validate that: // - bi_vec[0] is valid // - bi_vec[0].blob.blob_index() is valid @@ -1255,8 +1253,6 @@ impl BlobDevice { } else { let size = desc.bi_size; let mut f = BlobDeviceIoVec::new(self, desc); - // The `off` parameter to w.write_from() is actually ignored by - // BlobV5IoVec::read_vectored_at_volatile() w.write_from(&mut f, size as usize, 0) } } @@ -1420,28 +1416,12 @@ impl<'a> BlobDeviceIoVec<'a> { } } -impl FileReadWriteVolatile for BlobDeviceIoVec<'_> { - fn read_volatile(&mut self, _slice: FileVolatileSlice) -> Result { - // Skip because we don't really use it - unimplemented!(); - } - - fn write_volatile(&mut self, _slice: FileVolatileSlice) -> Result { - // Skip because we don't really use it - unimplemented!(); - } - - fn read_at_volatile(&mut self, slice: FileVolatileSlice, offset: u64) -> Result { - let buffers = [slice]; - self.read_vectored_at_volatile(&buffers, offset) - } - - // The default read_vectored_at_volatile only read to the first slice, so we have to overload it. +impl BlobIoRead for BlobDeviceIoVec<'_> { fn read_vectored_at_volatile( &mut self, - buffers: &[FileVolatileSlice], + buffers: &[VolatileSlice<'_>], _offset: u64, - ) -> Result { + ) -> io::Result { // BlobDevice::read_to() has validated that all IOs are against a single blob. let index = self.iovec.blob_index(); let blobs = &self.dev.blobs.load(); @@ -1457,14 +1437,6 @@ impl FileReadWriteVolatile for BlobDeviceIoVec<'_> { Err(einval!(msg)) } } - - fn write_at_volatile( - &mut self, - _slice: FileVolatileSlice, - _offset: u64, - ) -> Result { - unimplemented!() - } } /// Traits and Structs to support Rafs v5 image format. diff --git a/storage/src/lib.rs b/storage/src/lib.rs index 2776b37d072..0b8081b918c 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -55,6 +55,7 @@ pub mod meta; #[cfg(test)] pub(crate) mod test; pub mod utils; +pub mod volatile; // A helper to impl RafsChunkInfo for upper layers like Rafs different metadata mode. #[doc(hidden)] @@ -81,7 +82,6 @@ pub const RAFS_BATCH_SIZE_TO_GAP_SHIFT: u64 = 7; pub enum StorageError { Unsupported, Timeout, - VolatileSlice(vm_memory::VolatileMemoryError), MemOverflow, NotContinuous, CacheIndex(std::io::Error), @@ -96,7 +96,6 @@ impl Display for StorageError { StorageError::Timeout => write!(f, "timeout when reading data from storage backend"), StorageError::MemOverflow => write!(f, "memory overflow when doing storage backend IO"), StorageError::NotContinuous => write!(f, "address ranges are not continuous"), - StorageError::VolatileSlice(e) => write!(f, "{}", e), StorageError::CacheIndex(e) => write!(f, "Wrong cache index {}", e), StorageError::ProxyForbidden(s) => write!(f, "proxy forbidden: {}", s), StorageError::ProxyLimited(s) => write!(f, "proxy rate limited: {}", s), diff --git a/storage/src/meta/chunk_info_v1.rs b/storage/src/meta/chunk_info_v1.rs index 95429741019..335632aa2ee 100644 --- a/storage/src/meta/chunk_info_v1.rs +++ b/storage/src/meta/chunk_info_v1.rs @@ -156,9 +156,10 @@ mod tests { use std::mem::ManuallyDrop; use std::sync::Arc; + use crate::test::TempPath; use nydus_utils::compress; use nydus_utils::metrics::BackendMetrics; - use vmm_sys_util::tempfile::TempFile; + use tempfile::NamedTempFile as TempFile; use super::*; use crate::backend::BlobReader; diff --git a/storage/src/meta/toc.rs b/storage/src/meta/toc.rs index a4b12407843..bf1c18b316c 100644 --- a/storage/src/meta/toc.rs +++ b/storage/src/meta/toc.rs @@ -736,9 +736,10 @@ mod tests { use super::*; #[cfg(feature = "backend-localfs")] use crate::factory::BlobFactory; + use crate::test::TempPath; #[cfg(feature = "backend-localfs")] use nydus_api::{BackendConfigV2, LocalFsConfig}; - use vmm_sys_util::tempfile::TempFile; + use tempfile::NamedTempFile as TempFile; #[test] #[cfg(feature = "backend-localfs")] diff --git a/storage/src/remote/connection.rs b/storage/src/remote/connection.rs index 65d0d008bb0..d0f500a97dd 100644 --- a/storage/src/remote/connection.rs +++ b/storage/src/remote/connection.rs @@ -787,14 +787,14 @@ fn get_sub_iovs_offset(iov_lens: &[usize], skip_size: usize) -> (usize, usize) { #[cfg(test)] mod tests { use super::*; + use rand::distributions::{Alphanumeric, DistString}; use std::io::{Read, Seek, SeekFrom, Write}; - use vmm_sys_util::rand::rand_alphanumerics; - use vmm_sys_util::tempfile::TempFile; + use tempfile::NamedTempFile as TempFile; fn temp_path() -> PathBuf { PathBuf::from(format!( "/tmp/blob_test_{}", - rand_alphanumerics(8).to_str().unwrap() + Alphanumeric.sample_string(&mut rand::thread_rng(), 8) )) } diff --git a/storage/src/remote/server.rs b/storage/src/remote/server.rs index 8d1447f6376..55f0721c85d 100644 --- a/storage/src/remote/server.rs +++ b/storage/src/remote/server.rs @@ -346,8 +346,9 @@ impl AsRawFd for Server { #[cfg(test)] mod tests { use super::*; + use crate::test::TempPath; use std::time::{Duration, Instant}; - use vmm_sys_util::tempdir::TempDir; + use tempfile::TempDir; #[test] #[ignore] diff --git a/storage/src/test.rs b/storage/src/test.rs index 9c259a02ec7..6ff040bd7ab 100644 --- a/storage/src/test.rs +++ b/storage/src/test.rs @@ -3,7 +3,9 @@ // // SPDX-License-Identifier: Apache-2.0 +use std::path::Path; use std::sync::Arc; +use tempfile::{NamedTempFile, TempDir}; use nydus_utils::digest::RafsDigest; use nydus_utils::metrics::BackendMetrics; @@ -14,6 +16,22 @@ use crate::device::v5::BlobV5ChunkInfo; use crate::device::{BlobChunkFlags, BlobChunkInfo}; use std::any::Any; +pub(crate) trait TempPath { + fn as_path(&self) -> &Path; +} + +impl TempPath for NamedTempFile { + fn as_path(&self) -> &Path { + self.path() + } +} + +impl TempPath for TempDir { + fn as_path(&self) -> &Path { + self.path() + } +} + pub(crate) struct MockBackend { pub metrics: Arc, } diff --git a/storage/src/utils.rs b/storage/src/utils.rs index f9db014d8f4..e90c5f90a7e 100644 --- a/storage/src/utils.rs +++ b/storage/src/utils.rs @@ -4,8 +4,6 @@ // SPDX-License-Identifier: Apache-2.0 //! Utility helpers to support the storage subsystem. -use fuse_backend_rs::abi::fuse_abi::off64_t; -use fuse_backend_rs::file_buf::FileVolatileSlice; #[cfg(target_os = "macos")] use libc::{fcntl, radvisory}; use nix::sys::uio::preadv; @@ -24,14 +22,14 @@ use std::path::PathBuf; use std::slice::from_raw_parts_mut; #[cfg(target_os = "macos")] use std::{ffi::CStr, mem, os::raw::c_char}; -use vm_memory::bytes::Bytes; +use crate::volatile::VolatileSlice as FileVolatileSlice; use crate::{StorageError, StorageResult}; /// Just a simple wrapper for posix `preadv`. Provide a slice of `IoVec` as input. pub fn readv(fd: RawFd, iovec: &mut [IoSliceMut], offset: u64) -> Result { loop { - match preadv(fd, iovec, offset as off64_t).map_err(|_| last_error!()) { + match preadv(fd, iovec, offset as i64).map_err(|_| last_error!()) { Ok(ret) => return Ok(ret), // Retry if the IO is interrupted by signal. Err(err) if err.kind() != ErrorKind::Interrupted => return Err(err), @@ -77,9 +75,16 @@ pub fn copyv>( let dst_slice = &dst[dst_index]; let buffer = &s[src_offset..src_offset + buffer_len]; - let written = dst_slice - .write(buffer, dst_offset) - .map_err(StorageError::VolatileSlice)?; + let written = min(buffer.len(), dst_slice.len().saturating_sub(dst_offset)); + if written > 0 { + unsafe { + std::ptr::copy_nonoverlapping( + buffer.as_ptr(), + dst_slice.as_ptr().add(dst_offset), + written, + ); + } + } copied += written; if dst_slice.len() - dst_offset == written { @@ -358,8 +363,9 @@ pub fn check_crc(data: &[u8], crc_digest: u32) -> bool { #[cfg(test)] mod tests { use super::*; + use crate::test::TempPath; use std::io::Write; - use vmm_sys_util::tempfile::TempFile; + use tempfile::NamedTempFile as TempFile; #[test] fn test_copyv() { diff --git a/storage/src/volatile.rs b/storage/src/volatile.rs new file mode 100644 index 00000000000..aa364a299bc --- /dev/null +++ b/storage/src/volatile.rs @@ -0,0 +1,67 @@ +//! Volatile memory slice helpers owned by the storage crate. + +use std::io; + +use std::marker::PhantomData; + +/// A raw writable memory region used by storage read paths. +#[derive(Clone, Copy)] +pub struct VolatileSlice<'a> { + ptr: *mut u8, + len: usize, + phantom: PhantomData<&'a mut [u8]>, +} + +impl<'a> VolatileSlice<'a> { + /// Create a volatile slice from a raw pointer and length. + /// + /// # Safety + /// + /// The caller must ensure `ptr..ptr+len` is valid for writes for the lifetime `'a`. + pub unsafe fn from_raw_ptr(ptr: *mut u8, len: usize) -> Self { + Self { + ptr, + len, + phantom: PhantomData, + } + } + + /// Get the raw pointer backing the slice. + pub fn as_ptr(&self) -> *mut u8 { + self.ptr + } + + /// Get the length of the slice. + pub fn len(&self) -> usize { + self.len + } + + /// Check whether the slice is empty. + pub fn is_empty(&self) -> bool { + self.len == 0 + } +} + +/// Read chunk data into volatile memory slices. +pub trait BlobIoRead { + fn read_vectored_at_volatile( + &mut self, + buffers: &[VolatileSlice<'_>], + offset: u64, + ) -> io::Result; + + fn read_at_volatile(&mut self, slice: VolatileSlice<'_>, offset: u64) -> io::Result { + let buffers = [slice]; + self.read_vectored_at_volatile(&buffers, offset) + } +} + +/// Write chunk data from a volatile reader into a runtime-specific writer. +pub trait BlobIoWrite { + fn write_from( + &mut self, + reader: &mut dyn BlobIoRead, + size: usize, + offset: u64, + ) -> io::Result; +}