From 325ff62684cb0c642d2dd71d254e74e103452c95 Mon Sep 17 00:00:00 2001 From: loverustfs <155562731+loverustfs@users.noreply.github.com> Date: Fri, 31 Oct 2025 17:20:18 +0800 Subject: [PATCH] Issue 762 (#763) * Add InvalidRangeSpec error * Add EntityTooSmall to from_u32 * Add InvalidRangeSpec to from_u32 * Map InvalidRangeSpec to correct S3ErrorCode * Return Error::InvalidRangeSpec * Use auto implementation --------- Co-authored-by: Niklas Mollenhauer --- crates/ahm/src/heal/task.rs | 9 ++------- crates/common/src/heal_channel.rs | 18 ++++-------------- crates/ecstore/src/error.rs | 7 +++++++ crates/ecstore/src/store_api.rs | 12 ++++++------ crates/kms/src/config.rs | 10 ++-------- rustfs/src/error.rs | 1 + rustfs/src/storage/ecfs.rs | 2 +- 7 files changed, 23 insertions(+), 36 deletions(-) diff --git a/crates/ahm/src/heal/task.rs b/crates/ahm/src/heal/task.rs index b05a00a64..89c71b1bb 100644 --- a/crates/ahm/src/heal/task.rs +++ b/crates/ahm/src/heal/task.rs @@ -49,11 +49,12 @@ pub enum HealType { } /// Heal priority -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum HealPriority { /// Low priority Low = 0, /// Normal priority + #[default] Normal = 1, /// High priority High = 2, @@ -61,12 +62,6 @@ pub enum HealPriority { Urgent = 3, } -impl Default for HealPriority { - fn default() -> Self { - Self::Normal - } -} - /// Heal options #[derive(Debug, Clone, Serialize, Deserialize)] pub struct HealOptions { diff --git a/crates/common/src/heal_channel.rs b/crates/common/src/heal_channel.rs index 6988e06b8..746d9d1fc 100644 --- a/crates/common/src/heal_channel.rs +++ b/crates/common/src/heal_channel.rs @@ -85,19 +85,14 @@ impl Display for DriveState { } } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] pub enum HealScanMode { Unknown, + #[default] Normal, Deep, } -impl Default for HealScanMode { - fn default() -> Self { - Self::Normal - } -} - #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] pub struct HealOpts { pub recursive: bool, @@ -175,11 +170,12 @@ pub struct HealChannelResponse { } /// Heal priority -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum HealChannelPriority { /// Low priority Low, /// Normal priority + #[default] Normal, /// High priority High, @@ -187,12 +183,6 @@ pub enum HealChannelPriority { Critical, } -impl Default for HealChannelPriority { - fn default() -> Self { - Self::Normal - } -} - /// Heal channel sender pub type HealChannelSender = mpsc::UnboundedSender; diff --git a/crates/ecstore/src/error.rs b/crates/ecstore/src/error.rs index 77606f90d..01d57fbda 100644 --- a/crates/ecstore/src/error.rs +++ b/crates/ecstore/src/error.rs @@ -193,6 +193,9 @@ pub enum StorageError { #[error("Precondition failed")] PreconditionFailed, + + #[error("Invalid range specified: {0}")] + InvalidRangeSpec(String), } impl StorageError { @@ -424,6 +427,7 @@ impl Clone for StorageError { StorageError::InsufficientReadQuorum(a, b) => StorageError::InsufficientReadQuorum(a.clone(), b.clone()), StorageError::InsufficientWriteQuorum(a, b) => StorageError::InsufficientWriteQuorum(a.clone(), b.clone()), StorageError::PreconditionFailed => StorageError::PreconditionFailed, + StorageError::InvalidRangeSpec(a) => StorageError::InvalidRangeSpec(a.clone()), } } } @@ -491,6 +495,7 @@ impl StorageError { StorageError::InsufficientWriteQuorum(_, _) => 0x3A, StorageError::PreconditionFailed => 0x3B, StorageError::EntityTooSmall(_, _, _) => 0x3C, + StorageError::InvalidRangeSpec(_) => 0x3D, } } @@ -559,6 +564,8 @@ impl StorageError { 0x39 => Some(StorageError::InsufficientReadQuorum(Default::default(), Default::default())), 0x3A => Some(StorageError::InsufficientWriteQuorum(Default::default(), Default::default())), 0x3B => Some(StorageError::PreconditionFailed), + 0x3C => Some(StorageError::EntityTooSmall(Default::default(), Default::default(), Default::default())), + 0x3D => Some(StorageError::InvalidRangeSpec(Default::default())), _ => None, } } diff --git a/crates/ecstore/src/store_api.rs b/crates/ecstore/src/store_api.rs index d623513fa..7ee08e921 100644 --- a/crates/ecstore/src/store_api.rs +++ b/crates/ecstore/src/store_api.rs @@ -291,7 +291,7 @@ impl HTTPRangeSpec { let suffix_len = if self.start < 0 { self.start .checked_neg() - .ok_or_else(|| Error::other("range value invalid: suffix length overflow"))? + .ok_or_else(|| Error::InvalidRangeSpec("range value invalid: suffix length overflow".to_string()))? } else { self.start }; @@ -304,14 +304,14 @@ impl HTTPRangeSpec { } pub fn get_length(&self, res_size: i64) -> Result { if res_size < 0 { - return Err(Error::other("The requested range is not satisfiable")); + return Err(Error::InvalidRangeSpec("The requested range is not satisfiable".to_string())); } if self.is_suffix_length { let specified_len = if self.start < 0 { self.start .checked_neg() - .ok_or_else(|| Error::other("range value invalid: suffix length overflow"))? + .ok_or_else(|| Error::InvalidRangeSpec("range value invalid: suffix length overflow".to_string()))? } else { self.start }; @@ -325,7 +325,7 @@ impl HTTPRangeSpec { } if self.start >= res_size { - return Err(Error::other("The requested range is not satisfiable")); + return Err(Error::InvalidRangeSpec("The requested range is not satisfiable".to_string())); } if self.end > -1 { @@ -343,7 +343,7 @@ impl HTTPRangeSpec { return Ok(range_length); } - Err(Error::other(format!( + Err(Error::InvalidRangeSpec(format!( "range value invalid: start={}, end={}, expected start <= end and end >= -1", self.start, self.end ))) @@ -1361,7 +1361,7 @@ impl RangedDecompressReader { // Validate the range request if offset >= total_size { tracing::debug!("Range offset {} exceeds total size {}", offset, total_size); - return Err(Error::other("Range offset exceeds file size")); + return Err(Error::InvalidRangeSpec("Range offset exceeds file size".to_string())); } // Adjust length if it extends beyond file end diff --git a/crates/kms/src/config.rs b/crates/kms/src/config.rs index c3df3e885..299970b0c 100644 --- a/crates/kms/src/config.rs +++ b/crates/kms/src/config.rs @@ -21,21 +21,15 @@ use std::time::Duration; use url::Url; /// KMS backend types -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum KmsBackend { /// Vault backend (recommended for production) Vault, /// Local file-based backend for development and testing only + #[default] Local, } -impl Default for KmsBackend { - fn default() -> Self { - // Default to Local backend since Vault requires configuration - Self::Local - } -} - /// Main KMS configuration #[derive(Debug, Clone, Serialize, Deserialize)] pub struct KmsConfig { diff --git a/rustfs/src/error.rs b/rustfs/src/error.rs index 19041a8bf..a858cb495 100644 --- a/rustfs/src/error.rs +++ b/rustfs/src/error.rs @@ -83,6 +83,7 @@ impl From for ApiError { StorageError::InvalidPart(_, _, _) => S3ErrorCode::InvalidPart, StorageError::EntityTooSmall(_, _, _) => S3ErrorCode::EntityTooSmall, StorageError::PreconditionFailed => S3ErrorCode::PreconditionFailed, + StorageError::InvalidRangeSpec(_) => S3ErrorCode::InvalidRange, _ => S3ErrorCode::InternalError, }; diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 0e18e3c1f..d0e43366c 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -3202,7 +3202,7 @@ impl S3 for FS { range_spec .get_offset_length(validation_size) - .map_err(|e| S3Error::with_message(S3ErrorCode::InvalidRange, format!("Invalid range: {e}")))? + .map_err(|e| S3Error::with_message(S3ErrorCode::InvalidRange, e.to_string()))? } else { (0, src_info.size) };