fix(storage): avoid startup UUID disk lookup misses (#2576)

This commit is contained in:
weisd
2026-04-17 15:55:47 +08:00
committed by GitHub
parent f255b8a9f1
commit 8dc5ef6ef5
3 changed files with 115 additions and 3 deletions
+79 -1
View File
@@ -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;
+34 -2
View File
@@ -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,
+2
View File
@@ -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());