refactor(ecstore): add mmap copy disk read name (#4061)

This commit is contained in:
Zhengchao An
2026-06-29 21:18:41 +08:00
committed by GitHub
parent 9567e7b3be
commit a7dd9603e9
7 changed files with 53 additions and 30 deletions
+2 -2
View File
@@ -1361,9 +1361,9 @@ impl DiskAPI for LocalDiskWrapper {
.await
}
async fn read_file_zero_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<bytes::Bytes> {
async fn read_file_mmap_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<bytes::Bytes> {
self.track_disk_health(
|| async { self.disk.read_file_zero_copy(volume, path, offset, length).await },
|| async { self.disk.read_file_mmap_copy(volume, path, offset, length).await },
get_max_timeout_duration(),
)
.await
+23 -5
View File
@@ -2750,13 +2750,12 @@ impl DiskAPI for LocalDisk {
Ok(Box::new(StallTimeoutReader::new(reader, get_object_disk_read_timeout())))
}
/// Zero-copy file read using memory mapping (Unix) or efficient read (non-Unix).
/// Returns Bytes that can be shared without copying.
/// File read using mmap-then-copy on Unix or efficient read on non-Unix.
// SAFETY: Unix unsafe calls in this function only query page size and mmap
// a read-only file region after bounds and alignment are validated.
#[allow(unsafe_code)]
#[tracing::instrument(level = "debug", skip(self))]
async fn read_file_zero_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes> {
async fn read_file_mmap_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes> {
let volume_dir = self.get_bucket_path(volume)?;
if !skip_access_checks(volume) {
access(&volume_dir)
@@ -2784,7 +2783,7 @@ impl DiskAPI for LocalDisk {
offset,
length,
actual_size = meta.len(),
reason = "read_file_zero_copy_out_of_bounds",
reason = "read_file_mmap_copy_out_of_bounds",
"Disk local read fallback failed"
);
return Err(DiskError::FileCorrupt);
@@ -4871,7 +4870,26 @@ mod test {
}
#[tokio::test]
async fn test_read_file_zero_copy_rejects_offset_length_overflow() {
async fn test_read_file_mmap_copy_rejects_offset_length_overflow() {
use tempfile::tempdir;
let dir = tempdir().expect("operation should succeed");
let endpoint =
Endpoint::try_from(dir.path().to_str().expect("operation should succeed")).expect("operation should succeed");
let disk = LocalDisk::new(&endpoint, false).await.expect("operation should succeed");
disk.make_volume("test-volume").await.expect("operation should succeed");
disk.write_all("test-volume", "test-file.txt", Bytes::from_static(b"test"))
.await
.expect("operation should succeed");
let result = disk.read_file_mmap_copy("test-volume", "test-file.txt", usize::MAX, 1).await;
assert!(matches!(result, Err(DiskError::FileCorrupt)));
}
#[tokio::test]
#[allow(deprecated)]
async fn test_read_file_zero_copy_legacy_alias_rejects_offset_length_overflow() {
use tempfile::tempdir;
let dir = tempdir().expect("operation should succeed");
+14 -8
View File
@@ -291,10 +291,10 @@ impl DiskAPI for Disk {
}
#[tracing::instrument(skip(self))]
async fn read_file_zero_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes> {
async fn read_file_mmap_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes> {
match self {
Disk::Local(local_disk) => local_disk.read_file_zero_copy(volume, path, offset, length).await,
Disk::Remote(remote_disk) => remote_disk.read_file_zero_copy(volume, path, offset, length).await,
Disk::Local(local_disk) => local_disk.read_file_mmap_copy(volume, path, offset, length).await,
Disk::Remote(remote_disk) => remote_disk.read_file_mmap_copy(volume, path, offset, length).await,
}
}
@@ -558,11 +558,17 @@ pub trait DiskAPI: Debug + Send + Sync + 'static {
async fn read_file(&self, volume: &str, path: &str) -> Result<FileReader>;
async fn read_file_stream(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<FileReader>;
/// Zero-copy file read using memory mapping (Unix) or efficient read (non-Unix).
/// Returns Bytes that can be shared without copying.
/// On Unix, this uses mmap for true zero-copy access.
/// On other platforms, falls back to efficient read operations.
async fn read_file_zero_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes>;
/// File read using mmap-then-copy on Unix or an efficient read on non-Unix.
async fn read_file_mmap_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes>;
/// Historical name for `read_file_mmap_copy`.
#[deprecated(
since = "1.0.0-beta.8",
note = "use read_file_mmap_copy; this path copies mmap data into owned Bytes"
)]
async fn read_file_zero_copy(&self, volume: &str, path: &str, offset: usize, length: usize) -> Result<Bytes> {
self.read_file_mmap_copy(volume, path, offset, length).await
}
async fn append_file(&self, volume: &str, path: &str) -> Result<FileWriter>;
async fn create_file(&self, origvolume: &str, volume: &str, path: &str, file_size: i64) -> Result<FileWriter>;