fix(ecstore): harden runtime read-path quorum handling (#2872)

This commit is contained in:
houseme
2026-05-08 17:56:39 +08:00
committed by GitHub
parent 03045ff2e6
commit c90bfe2b23
21 changed files with 907 additions and 139 deletions
+43 -1
View File
@@ -31,7 +31,7 @@ use std::{
path::PathBuf,
sync::{
Arc,
atomic::{AtomicI64, AtomicU32, Ordering},
atomic::{AtomicI64, AtomicU32, AtomicU64, Ordering},
},
time::Duration,
};
@@ -138,6 +138,14 @@ pub struct DiskHealthTracker {
pub offline_since_unix_secs: AtomicI64,
/// Last runtime state transition timestamp
pub last_transition_unix_secs: AtomicI64,
/// Last successfully probed total space in bytes
pub last_capacity_total: AtomicU64,
/// Last successfully probed used space in bytes
pub last_capacity_used: AtomicU64,
/// Last successfully probed free space in bytes
pub last_capacity_free: AtomicU64,
/// Last successful capacity probe timestamp
pub last_capacity_probe_unix_secs: AtomicI64,
}
impl DiskHealthTracker {
@@ -158,6 +166,10 @@ impl DiskHealthTracker {
consecutive_successes: AtomicU32::new(0),
offline_since_unix_secs: AtomicI64::new(0),
last_transition_unix_secs: AtomicI64::new(now / 1_000_000_000),
last_capacity_total: AtomicU64::new(0),
last_capacity_used: AtomicU64::new(0),
last_capacity_free: AtomicU64::new(0),
last_capacity_probe_unix_secs: AtomicI64::new(0),
}
}
@@ -170,6 +182,28 @@ impl DiskHealthTracker {
self.last_success.store(now, Ordering::Relaxed);
}
pub fn record_capacity_probe(&self, total: u64, used: u64, free: u64) {
self.last_capacity_total.store(total, Ordering::Release);
self.last_capacity_used.store(used, Ordering::Release);
self.last_capacity_free.store(free, Ordering::Release);
self.last_capacity_probe_unix_secs
.store(current_unix_secs() as i64, Ordering::Release);
}
pub fn last_capacity_snapshot(&self) -> Option<(u64, u64, u64, u64)> {
let ts = self.last_capacity_probe_unix_secs.load(Ordering::Acquire);
if ts <= 0 {
return None;
}
Some((
self.last_capacity_total.load(Ordering::Acquire),
self.last_capacity_used.load(Ordering::Acquire),
self.last_capacity_free.load(Ordering::Acquire),
ts as u64,
))
}
/// Check if disk is faulty
pub fn is_faulty(&self) -> bool {
self.status.load(Ordering::Acquire) == DISK_HEALTH_FAULTY
@@ -463,6 +497,14 @@ impl LocalDiskWrapper {
self.health.offline_duration().map(|duration| duration.as_secs())
}
pub fn last_capacity_snapshot(&self) -> Option<(u64, u64, u64, u64)> {
self.health.last_capacity_snapshot()
}
pub fn record_capacity_probe(&self, total: u64, used: u64, free: u64) {
self.health.record_capacity_probe(total, used, free);
}
#[cfg(test)]
pub fn force_runtime_state_for_test(&self, state: RuntimeDriveHealthState) {
self.health.force_runtime_state_for_test(state);
+14
View File
@@ -427,6 +427,20 @@ impl Disk {
}
}
pub fn last_capacity_snapshot(&self) -> Option<(u64, u64, u64, u64)> {
match self {
Disk::Local(local_disk) => local_disk.last_capacity_snapshot(),
Disk::Remote(remote_disk) => remote_disk.last_capacity_snapshot(),
}
}
pub fn record_capacity_probe(&self, total: u64, used: u64, free: u64) {
match self {
Disk::Local(local_disk) => local_disk.record_capacity_probe(total, used, free),
Disk::Remote(remote_disk) => remote_disk.record_capacity_probe(total, used, free),
}
}
#[cfg(test)]
pub fn force_runtime_state_for_test(&self, state: RuntimeDriveHealthState) {
match self {