mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-03 02:38:12 +00:00
fix(scanner): fence system metadata publication (#6444)
* feat(scanner): fence usage publication during data movement * fix(scanner): detect movement refresh state changes * fix(scanner): fence publication during data movement * fix(scanner): close movement epoch publication races * fix(scanner): fence movement-sensitive publication paths * fix(scanner): fence cache and heal recovery paths * fix(scanner): carry publication epoch through scan cycle * fix(scanner): recheck remote cache epoch after save * fix(scanner): recheck local cache epoch before publish * fix(scanner): fence data usage writers and baseline * fix(scanner): expose decommission activity to publication fence * fix(scanner): release publication gate before reads * fix(scanner): complete publication fence integration * fix(scanner): avoid empty usage baseline publication * chore(scanner): gate test-only helpers * fix: use decommission canceler in reload test --------- Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -694,6 +694,11 @@ impl ECStore {
|
||||
/// callers only trigger missing-worker recovery after a real state change;
|
||||
/// delayed snapshots are merged monotonically and never blind-assigned.
|
||||
pub async fn reload_pool_meta(&self) -> Result<bool> {
|
||||
// Serialize the durable reload with local movement transitions. Loading
|
||||
// before acquiring this gate would allow a stale disk snapshot to
|
||||
// overwrite a newer local transition after the writer commits.
|
||||
let movement_gate = self.ctx.data_movement_operation_gate();
|
||||
let _movement_guard = movement_gate.write().await;
|
||||
let mut reloaded = PoolMeta::default();
|
||||
resolve_store_rebalance_pool_meta_reload_result(
|
||||
reloaded.load(self.pools[0].clone(), self.pools.clone()).await,
|
||||
@@ -701,15 +706,22 @@ impl ECStore {
|
||||
)?;
|
||||
|
||||
// Lock order: release the decommission_cancelers guard before taking
|
||||
// the pool_meta write guard; neither is held across the disk read.
|
||||
// the pool_meta write guard; neither is held without the movement gate.
|
||||
let active_workers = {
|
||||
let cancelers = self.decommission_cancelers.read().await;
|
||||
cancelers.iter().map(Option::is_some).collect::<Vec<_>>()
|
||||
cancelers
|
||||
.iter()
|
||||
.map(|canceler| canceler.as_ref().is_some_and(DecommissionCanceler::is_active))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
let incoming_has_pools = !reloaded.pools.is_empty();
|
||||
let mut pool_meta = self.pool_meta.write().await;
|
||||
let movement_before = pool_meta.clone();
|
||||
let merged_newer = merge_pool_status_refresh(&mut pool_meta, reloaded, &active_workers);
|
||||
if crate::core::pools::pool_meta_movement_snapshot_changed(&movement_before, &pool_meta) {
|
||||
self.ctx.advance_data_movement_operation_epoch();
|
||||
}
|
||||
|
||||
if !merged_newer && !incoming_has_pools {
|
||||
warn!(
|
||||
|
||||
Reference in New Issue
Block a user