mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 00:26:53 +00:00
fix(ecstore): remove reachable panics in tiering, replication, and heal paths (#4205)
* fix(ecstore): remove reachable panics in tiering, replication, and heal paths - Parse x-amz-expiration leniently in tier PUT responses; any lifecycle rule on the remote tier bucket returns an RFC1123 date that the previous ISO8601 unwrap turned into a panic of the ILM transition worker - Skip invalid user-metadata header values (with a warning) when building tier and replication PUT headers instead of panicking on non-ASCII input - Heal: tolerate absent data_dir for delete markers and remote objects - transition_object: don't unwrap version_id on unversioned buckets when recording partial writes for offline disks - Admin server info: use port_or_known_default() so default-port (80/443) endpoints don't panic is_server_resolvable - Tier ListObjectsV2 client: decode response body with from_utf8_lossy - walk_internal: log merge_entry_channels errors instead of dropping them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ecstore): fail heal explicitly when data_dir is missing Address review feedback: unwrap_or_default() silently substituted a nil UUID when latest metadata lacked data_dir. Delete markers and remote objects legitimately have no data_dir and skip the data-heal block, but for a regular object a missing data_dir means corrupt metadata — return FileCorrupt with a descriptive log instead of building part paths under a nil UUID directory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -352,8 +352,26 @@ impl SetDisks {
|
||||
|
||||
// We write at temporary location and then rename to final location.
|
||||
let tmp_id = Uuid::new_v4().to_string();
|
||||
let src_data_dir = latest_meta.data_dir.expect("operation should succeed").to_string();
|
||||
let dst_data_dir = latest_meta.data_dir.expect("operation should succeed");
|
||||
// Delete markers and remote (transitioned) objects carry no data_dir and
|
||||
// skip the data-heal block below, so a nil placeholder is safe for them.
|
||||
// For a regular object a missing data_dir means the latest metadata is
|
||||
// corrupt; fail this object's heal with a clear error instead of building
|
||||
// part paths under a nil UUID directory.
|
||||
let data_dir = match latest_meta.data_dir {
|
||||
Some(data_dir) => data_dir,
|
||||
None => {
|
||||
if !latest_meta.deleted && !latest_meta.is_remote() {
|
||||
error!(
|
||||
"heal: latest metadata for {}/{} has no data_dir, cannot heal object data",
|
||||
bucket, object
|
||||
);
|
||||
return Err(DiskError::FileCorrupt);
|
||||
}
|
||||
Uuid::nil()
|
||||
}
|
||||
};
|
||||
let src_data_dir = data_dir.to_string();
|
||||
let dst_data_dir = data_dir;
|
||||
|
||||
if !latest_meta.deleted && !latest_meta.is_remote() {
|
||||
let erasure_info = latest_meta.erasure.clone();
|
||||
|
||||
@@ -4446,7 +4446,9 @@ impl crate::storage_api_contracts::object::ObjectOperations for SetDisks {
|
||||
if let Some(disk) = disk {
|
||||
continue;
|
||||
}
|
||||
let _ = self.add_partial(bucket, object, opts.version_id.as_ref().expect("err")).await;
|
||||
let _ = self
|
||||
.add_partial(bucket, object, opts.version_id.as_deref().unwrap_or_default())
|
||||
.await;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user