mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-24 21:26:28 +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;
|
use peer::init_local_peer;
|
||||||
pub use 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,
|
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)]
|
#[derive(Debug)]
|
||||||
@@ -671,6 +671,17 @@ impl ServerPoolsAvailableSpace {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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]
|
#[tokio::test]
|
||||||
async fn test_get_disk_infos() {
|
async fn test_get_disk_infos() {
|
||||||
@@ -723,6 +734,73 @@ mod tests {
|
|||||||
assert!(result.is_none(), "Should return None for nonexistent path");
|
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]
|
#[tokio::test]
|
||||||
async fn test_all_local_disk_path() {
|
async fn test_all_local_disk_path() {
|
||||||
let paths = all_local_disk_path().await;
|
let paths = all_local_disk_path().await;
|
||||||
|
|||||||
@@ -15,6 +15,15 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::global::GLOBAL_LOCAL_DISK_ID_MAP;
|
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> {
|
pub async fn find_local_disk(disk_path: &String) -> Option<DiskStore> {
|
||||||
let disk_map = GLOBAL_LOCAL_DISK_MAP.read().await;
|
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> {
|
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 {
|
if let Some(disk) = find_local_disk(&disk_ref.to_string()).await {
|
||||||
|
let _ = remember_local_disk_id(&disk).await;
|
||||||
return Some(disk);
|
return Some(disk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,8 +44,19 @@ pub async fn find_local_disk_by_ref(disk_ref: &str) -> Option<DiskStore> {
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let disk_path = GLOBAL_LOCAL_DISK_ID_MAP.read().await.get(&disk_id).cloned()?;
|
if let Some(disk_path) = GLOBAL_LOCAL_DISK_ID_MAP.read().await.get(&disk_id).cloned()
|
||||||
find_local_disk(&disk_path).await
|
&& 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> {
|
pub async fn get_disk_via_endpoint(endpoint: &Endpoint) -> Option<DiskStore> {
|
||||||
@@ -70,6 +91,17 @@ pub async fn all_local_disk() -> Vec<DiskStore> {
|
|||||||
.collect()
|
.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<()> {
|
pub async fn init_local_disks(endpoint_pools: EndpointServerPools) -> Result<()> {
|
||||||
let opt = &DiskOption {
|
let opt = &DiskOption {
|
||||||
cleanup: true,
|
cleanup: true,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ use rustfs_ecstore::{
|
|||||||
set_global_endpoints,
|
set_global_endpoints,
|
||||||
store::ECStore,
|
store::ECStore,
|
||||||
store::init_local_disks,
|
store::init_local_disks,
|
||||||
|
store::prewarm_local_disk_id_map,
|
||||||
store_api::BucketOperations,
|
store_api::BucketOperations,
|
||||||
store_api::BucketOptions,
|
store_api::BucketOptions,
|
||||||
update_erasure_type,
|
update_erasure_type,
|
||||||
@@ -295,6 +296,7 @@ async fn run(config: rustfs::config::Config) -> Result<()> {
|
|||||||
|
|
||||||
// Initialize the local disk
|
// Initialize the local disk
|
||||||
init_local_disks(endpoint_pools.clone()).await.map_err(Error::other)?;
|
init_local_disks(endpoint_pools.clone()).await.map_err(Error::other)?;
|
||||||
|
prewarm_local_disk_id_map().await;
|
||||||
// Initialize the lock clients
|
// Initialize the lock clients
|
||||||
|
|
||||||
init_lock_clients(endpoint_pools.clone());
|
init_lock_clients(endpoint_pools.clone());
|
||||||
|
|||||||
Reference in New Issue
Block a user