mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-07 12:35:54 +00:00
fix(scanner): recover fenced incomplete usage floors (#7055)
* fix(scanner): recover fenced incomplete usage floors * fix(scanner): validate legacy usage floor shape Co-Authored-By: heihutu <heihutu@gmail.com> --------- Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
@@ -552,18 +552,21 @@ pub(super) fn data_usage_info_has_persisted_baseline_identity(info: &DataUsageIn
|
||||
}
|
||||
|
||||
pub(super) fn data_usage_info_is_bootstrap_pending(info: &DataUsageInfo) -> bool {
|
||||
if info.last_update.is_none() || info.scanner_cycle.is_some() {
|
||||
let Some(last_update) = info.last_update else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let expected = DataUsageInfo {
|
||||
last_update: info.last_update,
|
||||
scanner_epoch: info.scanner_epoch,
|
||||
info == &scanner_usage_bootstrap_marker(last_update, info.scanner_epoch)
|
||||
}
|
||||
|
||||
pub(super) fn scanner_usage_bootstrap_marker(last_update: std::time::SystemTime, scanner_epoch: Option<u64>) -> DataUsageInfo {
|
||||
DataUsageInfo {
|
||||
last_update: Some(last_update),
|
||||
scanner_epoch,
|
||||
usage_snapshot_converged: Some(false),
|
||||
usage_snapshot_bootstrap_pending: true,
|
||||
..Default::default()
|
||||
};
|
||||
info == &expected
|
||||
}
|
||||
}
|
||||
|
||||
fn usage_cache_needs_prompt_scan(authoritative: &DataUsageInfo, observed: Option<&DataUsageInfo>) -> bool {
|
||||
@@ -915,8 +918,8 @@ fn prepare_cycle_for_usage_floor_bootstrap(
|
||||
},
|
||||
)
|
||||
}
|
||||
PersistedUsageFloorStartup::RecoveredLegacyEmptyFence => {
|
||||
// The legacy empty fence proves only its leader epoch, not
|
||||
PersistedUsageFloorStartup::RecoveredLegacyIncompleteFence => {
|
||||
// The legacy incomplete fence proves only its leader epoch, not
|
||||
// namespace coverage. Clear coverage while retaining the durable
|
||||
// cycle number so surviving caches cannot force a regression.
|
||||
let next = cycle_info.next;
|
||||
@@ -1438,6 +1441,7 @@ async fn fence_scanner_epoch_after_cycle_timeout<Store, LockLost>(
|
||||
cycle_info: &mut CurrentCycle,
|
||||
cycle_revision: &mut DataUsageCacheRevision,
|
||||
leader_epoch: &mut u64,
|
||||
allow_bootstrap_pending: bool,
|
||||
lock_lost: LockLost,
|
||||
) -> bool
|
||||
where
|
||||
@@ -1451,7 +1455,7 @@ where
|
||||
cycle_info,
|
||||
cycle_revision,
|
||||
leader_epoch,
|
||||
false,
|
||||
allow_bootstrap_pending,
|
||||
ScannerCycleResetPolicy::None,
|
||||
);
|
||||
tokio::pin!(claim);
|
||||
@@ -1473,6 +1477,7 @@ struct ScannerCycleDeadlineState<'a> {
|
||||
cycle_revision: &'a mut DataUsageCacheRevision,
|
||||
leader_epoch: &'a mut u64,
|
||||
cycle_budget: &'a ScannerCycleBudget,
|
||||
allow_bootstrap_pending: bool,
|
||||
}
|
||||
|
||||
fn cycle_timeout_requires_recovery(worker_stopped: bool, cycle_state_persisted: bool, generation_fenced: bool) -> bool {
|
||||
@@ -1494,6 +1499,7 @@ async fn handle_scanner_cycle_deadline<Store>(
|
||||
state.cycle_info,
|
||||
state.cycle_revision,
|
||||
state.leader_epoch,
|
||||
state.allow_bootstrap_pending,
|
||||
guard.lock_lost_notified(),
|
||||
)
|
||||
.await;
|
||||
@@ -2575,7 +2581,7 @@ async fn run_data_scanner_with_maintenance_state(
|
||||
match usage_floor_startup {
|
||||
PersistedUsageFloorStartup::Authoritative
|
||||
| PersistedUsageFloorStartup::BootstrapPending
|
||||
| PersistedUsageFloorStartup::RecoveredLegacyEmptyFence => {}
|
||||
| PersistedUsageFloorStartup::RecoveredLegacyIncompleteFence => {}
|
||||
PersistedUsageFloorStartup::Missing => {
|
||||
if ctx.is_cancelled() || guard.is_lock_lost() {
|
||||
global_metrics().set_cycle(None).await;
|
||||
@@ -2670,8 +2676,8 @@ async fn run_data_scanner_with_maintenance_state(
|
||||
finish_scanner_leader_iteration(false, "epoch_claim_failed", "leadership epoch claim failed".to_string()).await;
|
||||
return Ok(());
|
||||
}
|
||||
if usage_floor_startup == PersistedUsageFloorStartup::RecoveredLegacyEmptyFence
|
||||
&& let Err(err) = complete_legacy_empty_usage_floor_recovery(storeapi.clone(), leader_epoch).await
|
||||
if usage_floor_startup == PersistedUsageFloorStartup::RecoveredLegacyIncompleteFence
|
||||
&& let Err(err) = complete_legacy_incomplete_usage_floor_recovery(storeapi.clone(), leader_epoch).await
|
||||
{
|
||||
let error = err.to_string();
|
||||
warn!(
|
||||
@@ -2744,6 +2750,7 @@ async fn run_data_scanner_with_maintenance_state(
|
||||
cycle_revision: &mut cycle_revision,
|
||||
leader_epoch: &mut leader_epoch,
|
||||
cycle_budget: &cycle_budget,
|
||||
allow_bootstrap_pending: allow_usage_floor_bootstrap_pending,
|
||||
},
|
||||
worker_stopped,
|
||||
&mut guard,
|
||||
@@ -3033,6 +3040,7 @@ async fn run_data_scanner_with_maintenance_state(
|
||||
cycle_revision: &mut cycle_revision,
|
||||
leader_epoch: &mut leader_epoch,
|
||||
cycle_budget: &cycle_budget,
|
||||
allow_bootstrap_pending: allow_usage_floor_bootstrap_pending,
|
||||
},
|
||||
worker_stopped,
|
||||
&mut guard,
|
||||
|
||||
Reference in New Issue
Block a user