mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-23 20:59:05 +00:00
fix(ecstore): fence deletes against decommission commits (#6363)
* fix(ecstore): fence deletes against decommission commits * fix(ecstore): preserve decommission target write locks * fix(ecstore): preserve delete markers during source cleanup * fix(ecstore): route batch delete markers to active pools * fix(ecstore): preserve batch delete pool errors * fix(ecstore): retain source-set lock during cleanup * test(ecstore): exercise decommission delete fences * test(ecstore): finish decommission delete fence scenario * fix(ecstore): reuse fixed fence for reverse decommission * fix(ecstore): fence decommission commit loss * fix(ecstore): annotate batch delete fallback * test(ecstore): fix decommission fence fixtures * fix(ecstore): unblock decommission delete fences * fix(ecstore): preserve distributed decommission set locks * fix(ecstore): match decommission lock backend domain * test(ecstore): align decommission fence barriers * fix(ecstore): satisfy delete fence lint checks * fix(rebalance): preserve access-denied delete errors
This commit is contained in:
@@ -3673,6 +3673,9 @@ impl ECStore {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let source_cleanup_mutation_fence = self
|
||||
.acquire_decommission_source_cleanup_fence(bucket.as_str(), entry.name.as_str(), set.as_ref())
|
||||
.await?;
|
||||
let cleanup_result = data_movement::cleanup_source_entry_if_unchanged(
|
||||
set.clone(),
|
||||
bucket.as_str(),
|
||||
@@ -3684,6 +3687,7 @@ impl ECStore {
|
||||
lifecycle_guard: bucket_incarnation_fence
|
||||
.as_ref()
|
||||
.and_then(|guard| guard.namespace_lock_guard()),
|
||||
object_mutation_fence: Some(&source_cleanup_mutation_fence),
|
||||
},
|
||||
"decommission",
|
||||
)
|
||||
@@ -3785,6 +3789,22 @@ impl ECStore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn decommission_entry_for_test(
|
||||
self: &Arc<Self>,
|
||||
idx: usize,
|
||||
entry: MetaCacheEntry,
|
||||
bucket: String,
|
||||
set: Arc<SetDisks>,
|
||||
) -> Result<()> {
|
||||
let worker_permit = Arc::new(Semaphore::new(1))
|
||||
.acquire_owned()
|
||||
.await
|
||||
.map_err(|err| Error::other(format!("decommission test worker permit acquire failed: {err}")))?;
|
||||
self.decommission_entry(CancellationToken::new(), idx, entry, bucket, set, worker_permit, None, None, None, None)
|
||||
.await
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, rx))]
|
||||
async fn decommission_pool(
|
||||
self: &Arc<Self>,
|
||||
@@ -4821,15 +4841,20 @@ impl ECStore {
|
||||
) -> Result<()> {
|
||||
warn!("decommission_object: start {} {}", &bucket, &rd.object_info.name);
|
||||
let object_name = rd.object_info.name.clone();
|
||||
let result = data_movement::migrate_object(
|
||||
let mut migration = tokio::task::JoinSet::new();
|
||||
migration.spawn(data_movement::migrate_decommission_object(
|
||||
self,
|
||||
pool_idx,
|
||||
bucket.clone(),
|
||||
rd,
|
||||
expected_bucket_incarnation_id,
|
||||
"decommission_object",
|
||||
)
|
||||
.await;
|
||||
));
|
||||
let result = migration
|
||||
.join_next()
|
||||
.await
|
||||
.ok_or_else(|| Error::other("decommission migration task was not started"))?
|
||||
.map_err(|err| Error::other(format!("decommission migration task join error: {err}")))?;
|
||||
if result.is_ok() {
|
||||
warn!("decommission_object: migrated {} {}", &bucket, &object_name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user