Skip to content

Commit 69ffb12

Browse files
committed
Merge branch 'main' of https://github.com/0x7d8/wings-rs
2 parents 20fcb99 + 68bd4f7 commit 69ffb12

2 files changed

Lines changed: 63 additions & 30 deletions

File tree

application/src/server/backup/adapters/zfs.rs

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,58 @@ impl ZfsBackup {
7474

7575
Ok(ignore_builder.build()?)
7676
}
77+
78+
async fn destroy_snapshot(target: &str) -> Result<(), anyhow::Error> {
79+
let backoffs_ms = [100u64, 200, 400, 800, 1600, 3200];
80+
81+
for backoff_ms in backoffs_ms {
82+
let output = Command::new("zfs")
83+
.arg("destroy")
84+
.arg("-f")
85+
.arg(target)
86+
.env("LC_ALL", "C")
87+
.output()
88+
.await?;
89+
90+
if output.status.success() {
91+
return Ok(());
92+
}
93+
94+
let stderr = String::from_utf8_lossy(&output.stderr);
95+
96+
if stderr.contains("could not find any snapshots to destroy") {
97+
return Ok(());
98+
}
99+
100+
if !stderr.contains("dataset is busy") {
101+
return Err(anyhow::anyhow!("failed to delete zfs snapshot: {}", stderr));
102+
}
103+
104+
tokio::time::sleep(std::time::Duration::from_millis(backoff_ms)).await;
105+
}
106+
107+
// Deferred destroy so the user-visible delete completes even if a kernel reference lingers.
108+
let output = Command::new("zfs")
109+
.arg("destroy")
110+
.arg("-d")
111+
.arg(target)
112+
.env("LC_ALL", "C")
113+
.output()
114+
.await?;
115+
116+
let stderr = String::from_utf8_lossy(&output.stderr);
117+
118+
if !output.status.success() && !stderr.contains("could not find any snapshots to destroy") {
119+
return Err(anyhow::anyhow!("failed to delete zfs snapshot: {}", stderr));
120+
}
121+
122+
tracing::warn!(
123+
snapshot = %target,
124+
"zfs snapshot still busy after retries; marked for deferred destroy"
125+
);
126+
127+
Ok(())
128+
}
77129
}
78130

79131
#[async_trait::async_trait]
@@ -433,21 +485,7 @@ impl BackupExt for ZfsBackup {
433485
.await;
434486

435487
if let Ok(dataset_name) = tokio::fs::read_to_string(dataset_path).await {
436-
let output = Command::new("zfs")
437-
.arg("destroy")
438-
.arg("-f")
439-
.arg(format!("{}@{}", dataset_name.trim(), snapshot_name))
440-
.env("LC_ALL", "C")
441-
.output()
442-
.await?;
443-
444-
let stderr = String::from_utf8_lossy(&output.stderr);
445-
446-
if !output.status.success()
447-
&& !stderr.contains("could not find any snapshots to destroy")
448-
{
449-
return Err(anyhow::anyhow!("failed to delete zfs snapshot: {}", stderr));
450-
}
488+
Self::destroy_snapshot(&format!("{}@{}", dataset_name.trim(), snapshot_name)).await?;
451489
}
452490

453491
tokio::fs::remove_dir_all(backup_path).await?;
@@ -491,22 +529,14 @@ impl BackupCleanExt for ZfsBackup {
491529
return Ok(());
492530
}
493531

494-
if let Ok(dataset_name) = tokio::fs::read_to_string(dataset_path).await {
495-
let output = Command::new("zfs")
496-
.arg("destroy")
497-
.arg("-f")
498-
.arg(format!("{}@{}", dataset_name.trim(), snapshot_name))
499-
.env("LC_ALL", "C")
500-
.output()
501-
.await?;
502-
503-
let stderr = String::from_utf8_lossy(&output.stderr);
532+
server
533+
.app_state
534+
.backup_manager
535+
.invalidate_cached_browse(uuid)
536+
.await;
504537

505-
if !output.status.success()
506-
&& !stderr.contains("could not find any snapshots to destroy")
507-
{
508-
return Err(anyhow::anyhow!("failed to delete zfs snapshot: {}", stderr));
509-
}
538+
if let Ok(dataset_name) = tokio::fs::read_to_string(dataset_path).await {
539+
Self::destroy_snapshot(&format!("{}@{}", dataset_name.trim(), snapshot_name)).await?;
510540
}
511541

512542
tokio::fs::remove_dir_all(backup_path).await?;

application/src/server/backup/manager.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,5 +503,8 @@ impl BackupManager {
503503
{
504504
tracing::error!(backup = %uuid, "failed to close cached browse backup: {:#?}", err);
505505
}
506+
507+
self.cached_browse_backups.run_pending_tasks().await;
508+
self.cached_browse_backup_locks.run_pending_tasks().await;
506509
}
507510
}

0 commit comments

Comments
 (0)