mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
fix(storage): avoid startup UUID disk lookup misses (#2576)
This commit is contained in:
@@ -163,7 +163,7 @@ mod rebalance;
|
||||
use peer::init_local_peer;
|
||||
pub use peer::{
|
||||
all_local_disk, all_local_disk_path, find_local_disk, find_local_disk_by_ref, get_disk_infos, get_disk_via_endpoint,
|
||||
has_space_for, init_local_disks, init_lock_clients,
|
||||
has_space_for, init_local_disks, init_lock_clients, prewarm_local_disk_id_map,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -671,6 +671,17 @@ impl ServerPoolsAvailableSpace {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::endpoints::{Endpoints, PoolEndpoints};
|
||||
use crate::global::{GLOBAL_LOCAL_DISK_ID_MAP, GLOBAL_LOCAL_DISK_MAP, GLOBAL_LOCAL_DISK_SET_DRIVES};
|
||||
use crate::store_init::{connect_load_init_formats, init_disks};
|
||||
use serial_test::serial;
|
||||
use tempfile::TempDir;
|
||||
|
||||
async fn reset_local_disk_globals() {
|
||||
GLOBAL_LOCAL_DISK_MAP.write().await.clear();
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.write().await.clear();
|
||||
GLOBAL_LOCAL_DISK_SET_DRIVES.write().await.clear();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_disk_infos() {
|
||||
@@ -723,6 +734,73 @@ mod tests {
|
||||
assert!(result.is_none(), "Should return None for nonexistent path");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_find_local_disk_by_ref_backfills_uuid_map() {
|
||||
reset_local_disk_globals().await;
|
||||
|
||||
let temp_dir = TempDir::new().expect("create temp dir for local disk ref test");
|
||||
let disk_paths = (0..4)
|
||||
.map(|idx| temp_dir.path().join(format!("disk{}", idx + 1)))
|
||||
.collect::<Vec<_>>();
|
||||
for disk_path in &disk_paths {
|
||||
std::fs::create_dir_all(disk_path).expect("create disk path");
|
||||
}
|
||||
|
||||
let mut endpoints = Vec::new();
|
||||
for (idx, disk_path) in disk_paths.iter().enumerate() {
|
||||
let mut endpoint = Endpoint::try_from(disk_path.to_str().expect("disk path to str")).expect("endpoint");
|
||||
endpoint.set_pool_index(0);
|
||||
endpoint.set_set_index(0);
|
||||
endpoint.set_disk_index(idx);
|
||||
endpoints.push(endpoint);
|
||||
}
|
||||
|
||||
let endpoint_pools = EndpointServerPools(vec![PoolEndpoints {
|
||||
legacy: false,
|
||||
set_count: 1,
|
||||
drives_per_set: 4,
|
||||
endpoints: Endpoints::from(endpoints),
|
||||
cmd_line: "find-local-disk-by-ref-test".to_string(),
|
||||
platform: "test".to_string(),
|
||||
}]);
|
||||
|
||||
init_local_disks(endpoint_pools.clone()).await.expect("init local disks");
|
||||
|
||||
let (disks, errs) = init_disks(
|
||||
&endpoint_pools.as_ref().first().expect("pool endpoints").endpoints,
|
||||
&DiskOption {
|
||||
cleanup: true,
|
||||
health_check: false,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(errs.iter().all(|err| err.is_none()), "disk init should succeed: {errs:?}");
|
||||
connect_load_init_formats(true, &disks, 1, 4, None)
|
||||
.await
|
||||
.expect("initialize format metadata");
|
||||
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.write().await.clear();
|
||||
|
||||
let local_disks = all_local_disk().await;
|
||||
let first_disk = local_disks.first().expect("local disk exists");
|
||||
let disk_id = first_disk
|
||||
.get_disk_id()
|
||||
.await
|
||||
.expect("get disk id should succeed")
|
||||
.expect("disk id should exist");
|
||||
|
||||
let found = find_local_disk_by_ref(&disk_id.to_string()).await;
|
||||
assert!(found.is_some(), "disk lookup by id should backfill cache");
|
||||
assert_eq!(
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.read().await.get(&disk_id).cloned(),
|
||||
Some(first_disk.endpoint().to_string())
|
||||
);
|
||||
|
||||
reset_local_disk_globals().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_local_disk_path() {
|
||||
let paths = all_local_disk_path().await;
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
use super::*;
|
||||
use crate::global::GLOBAL_LOCAL_DISK_ID_MAP;
|
||||
|
||||
async fn remember_local_disk_id(disk: &DiskStore) -> Option<Uuid> {
|
||||
let disk_id = disk.get_disk_id().await.ok().flatten()?;
|
||||
GLOBAL_LOCAL_DISK_ID_MAP
|
||||
.write()
|
||||
.await
|
||||
.insert(disk_id, disk.endpoint().to_string());
|
||||
Some(disk_id)
|
||||
}
|
||||
|
||||
pub async fn find_local_disk(disk_path: &String) -> Option<DiskStore> {
|
||||
let disk_map = GLOBAL_LOCAL_DISK_MAP.read().await;
|
||||
|
||||
@@ -27,6 +36,7 @@ pub async fn find_local_disk(disk_path: &String) -> Option<DiskStore> {
|
||||
|
||||
pub async fn find_local_disk_by_ref(disk_ref: &str) -> Option<DiskStore> {
|
||||
if let Some(disk) = find_local_disk(&disk_ref.to_string()).await {
|
||||
let _ = remember_local_disk_id(&disk).await;
|
||||
return Some(disk);
|
||||
}
|
||||
|
||||
@@ -34,8 +44,19 @@ pub async fn find_local_disk_by_ref(disk_ref: &str) -> Option<DiskStore> {
|
||||
return None;
|
||||
};
|
||||
|
||||
let disk_path = GLOBAL_LOCAL_DISK_ID_MAP.read().await.get(&disk_id).cloned()?;
|
||||
find_local_disk(&disk_path).await
|
||||
if let Some(disk_path) = GLOBAL_LOCAL_DISK_ID_MAP.read().await.get(&disk_id).cloned()
|
||||
&& let Some(disk) = find_local_disk(&disk_path).await
|
||||
{
|
||||
return Some(disk);
|
||||
}
|
||||
|
||||
for disk in all_local_disk().await {
|
||||
if remember_local_disk_id(&disk).await == Some(disk_id) {
|
||||
return Some(disk);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn get_disk_via_endpoint(endpoint: &Endpoint) -> Option<DiskStore> {
|
||||
@@ -70,6 +91,17 @@ pub async fn all_local_disk() -> Vec<DiskStore> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn prewarm_local_disk_id_map() {
|
||||
for disk in all_local_disk().await {
|
||||
if let Err(err) = disk.get_disk_id().await {
|
||||
warn!("prewarm_local_disk_id_map: failed to load disk id for {}: {}", disk.endpoint(), err);
|
||||
continue;
|
||||
}
|
||||
|
||||
let _ = remember_local_disk_id(&disk).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_local_disks(endpoint_pools: EndpointServerPools) -> Result<()> {
|
||||
let opt = &DiskOption {
|
||||
cleanup: true,
|
||||
|
||||
@@ -44,6 +44,7 @@ use rustfs_ecstore::{
|
||||
set_global_endpoints,
|
||||
store::ECStore,
|
||||
store::init_local_disks,
|
||||
store::prewarm_local_disk_id_map,
|
||||
store_api::BucketOperations,
|
||||
store_api::BucketOptions,
|
||||
update_erasure_type,
|
||||
@@ -295,6 +296,7 @@ async fn run(config: rustfs::config::Config) -> Result<()> {
|
||||
|
||||
// Initialize the local disk
|
||||
init_local_disks(endpoint_pools.clone()).await.map_err(Error::other)?;
|
||||
prewarm_local_disk_id_map().await;
|
||||
// Initialize the lock clients
|
||||
|
||||
init_lock_clients(endpoint_pools.clone());
|
||||
|
||||
Reference in New Issue
Block a user