mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-13 08:36:54 +00:00
fix(ecstore): quarantine rejected format members (#5463)
This commit is contained in:
@@ -27,7 +27,7 @@ use crate::{
|
||||
bucket::replication::{DynReplicationPool, ReplicationStats},
|
||||
config::{get_global_storage_class, get_global_storage_class_snapshot, set_global_storage_class, storageclass},
|
||||
disk::{DiskAPI, DiskOption, DiskStore, new_disk},
|
||||
error::Result,
|
||||
error::{Error, Result},
|
||||
layout::endpoints::{EndpointServerPools, SetupType},
|
||||
runtime::global::{
|
||||
GLOBAL_BOOT_TIME, GLOBAL_LIFECYCLE_SYS, GLOBAL_LOCAL_NODE_NAME_FALLBACK, GLOBAL_ROOT_DISK_THRESHOLD,
|
||||
@@ -417,10 +417,6 @@ pub(crate) async fn clear_local_disk_id_map_for_test() {
|
||||
local_disk_id_map_handle().write().await.clear();
|
||||
}
|
||||
|
||||
pub(crate) async fn record_local_disk_id(instance_ctx: &Arc<InstanceContext>, disk_id: Uuid, endpoint: String) {
|
||||
instance_ctx.local_disk_id_map().write().await.insert(disk_id, endpoint);
|
||||
}
|
||||
|
||||
pub(crate) async fn replace_local_disk_id(previous: Option<Uuid>, current: Option<Uuid>, endpoint: String) {
|
||||
let id_map = local_disk_id_map_handle();
|
||||
let mut disk_id_map = id_map.write().await;
|
||||
@@ -436,6 +432,53 @@ pub(crate) async fn replace_local_disk_id(previous: Option<Uuid>, current: Optio
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn reconcile_local_disk_ids(
|
||||
instance_ctx: &InstanceContext,
|
||||
pool_endpoints: &[String],
|
||||
selected: &[(Uuid, String)],
|
||||
) {
|
||||
let pool_endpoints = pool_endpoints.iter().map(String::as_str).collect::<HashSet<_>>();
|
||||
let disk_id_map = instance_ctx.local_disk_id_map();
|
||||
let mut disk_ids = disk_id_map.write().await;
|
||||
disk_ids.retain(|_, registered_endpoint| !pool_endpoints.contains(registered_endpoint.as_str()));
|
||||
disk_ids.extend(selected.iter().cloned());
|
||||
}
|
||||
|
||||
pub(crate) async fn quarantine_local_disks(instance_ctx: &InstanceContext, endpoints: &[Endpoint]) -> Result<()> {
|
||||
let slots = endpoints
|
||||
.iter()
|
||||
.map(|endpoint| {
|
||||
Ok((
|
||||
usize::try_from(endpoint.pool_idx).map_err(|_| Error::CorruptedFormat)?,
|
||||
usize::try_from(endpoint.set_idx).map_err(|_| Error::CorruptedFormat)?,
|
||||
usize::try_from(endpoint.disk_idx).map_err(|_| Error::CorruptedFormat)?,
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let local_disk_map = instance_ctx.local_disk_map();
|
||||
let mut local_disks = local_disk_map.write().await;
|
||||
for endpoint in endpoints {
|
||||
local_disks.insert(endpoint.to_string(), None);
|
||||
}
|
||||
drop(local_disks);
|
||||
|
||||
let set_drives = instance_ctx.local_disk_set_drives();
|
||||
let mut local_set_drives = set_drives.write().await;
|
||||
if local_set_drives.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
for (pool_idx, set_idx, disk_idx) in slots {
|
||||
let disk = local_set_drives
|
||||
.get_mut(pool_idx)
|
||||
.and_then(|sets| sets.get_mut(set_idx))
|
||||
.and_then(|disks| disks.get_mut(disk_idx))
|
||||
.ok_or(Error::CorruptedFormat)?;
|
||||
*disk = None;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn record_local_disks(instance_ctx: &Arc<InstanceContext>, disks: Vec<DiskStore>) {
|
||||
let map = instance_ctx.local_disk_map();
|
||||
let mut global_local_disk_map = map.write().await;
|
||||
@@ -563,8 +606,8 @@ pub(crate) async fn init_tier_config_mgr(store: Arc<ECStore>) -> Result<()> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
LockRegistry, clear_local_disk_id_map_for_test, local_disk_path_by_id, local_node_name, replace_local_disk_id,
|
||||
set_local_node_name,
|
||||
LockRegistry, clear_local_disk_id_map_for_test, local_disk_path_by_id, local_node_name, reconcile_local_disk_ids,
|
||||
replace_local_disk_id, set_local_node_name,
|
||||
};
|
||||
use crate::disk::endpoint::Endpoint;
|
||||
use rustfs_lock::{LocalClient, LockClient};
|
||||
@@ -628,4 +671,65 @@ mod tests {
|
||||
assert_eq!(local_disk_path_by_id(&disk_id).await, Some("endpoint-a".to_string()));
|
||||
clear_local_disk_id_map_for_test().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn reconciling_pool_disk_ids_preserves_other_endpoints() {
|
||||
let instance_ctx = Arc::new(crate::runtime::instance::InstanceContext::new());
|
||||
let process_ctx = crate::runtime::global::current_ctx();
|
||||
let bootstrap_ctx = crate::runtime::instance::bootstrap_ctx();
|
||||
let retained_id = Uuid::new_v4();
|
||||
let removed_id = Uuid::new_v4();
|
||||
let selected_id = Uuid::new_v4();
|
||||
let process_sentinel = Uuid::new_v4();
|
||||
let bootstrap_sentinel = Uuid::new_v4();
|
||||
instance_ctx.local_disk_id_map().write().await.extend([
|
||||
(retained_id, "endpoint-a".to_string()),
|
||||
(removed_id, "endpoint-b".to_string()),
|
||||
]);
|
||||
process_ctx
|
||||
.local_disk_id_map()
|
||||
.write()
|
||||
.await
|
||||
.insert(process_sentinel, "endpoint-b".to_string());
|
||||
bootstrap_ctx
|
||||
.local_disk_id_map()
|
||||
.write()
|
||||
.await
|
||||
.insert(bootstrap_sentinel, "endpoint-b".to_string());
|
||||
|
||||
reconcile_local_disk_ids(
|
||||
&instance_ctx,
|
||||
&["endpoint-b".to_string(), "endpoint-c".to_string()],
|
||||
&[(selected_id, "endpoint-c".to_string())],
|
||||
)
|
||||
.await;
|
||||
|
||||
let disk_ids = instance_ctx.local_disk_id_map();
|
||||
let disk_ids = disk_ids.read().await;
|
||||
assert_eq!(disk_ids.get(&retained_id).map(String::as_str), Some("endpoint-a"));
|
||||
assert_eq!(disk_ids.get(&removed_id), None);
|
||||
assert_eq!(disk_ids.get(&selected_id).map(String::as_str), Some("endpoint-c"));
|
||||
drop(disk_ids);
|
||||
assert_eq!(
|
||||
process_ctx
|
||||
.local_disk_id_map()
|
||||
.read()
|
||||
.await
|
||||
.get(&process_sentinel)
|
||||
.map(String::as_str),
|
||||
Some("endpoint-b")
|
||||
);
|
||||
assert_eq!(
|
||||
bootstrap_ctx
|
||||
.local_disk_id_map()
|
||||
.read()
|
||||
.await
|
||||
.get(&bootstrap_sentinel)
|
||||
.map(String::as_str),
|
||||
Some("endpoint-b")
|
||||
);
|
||||
process_ctx.local_disk_id_map().write().await.remove(&process_sentinel);
|
||||
bootstrap_ctx.local_disk_id_map().write().await.remove(&bootstrap_sentinel);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user