# Proxmox Backup Server auf ZFS: Datastore voll („No space left on device“)

**Symptom:** Backups scheitern mit `No space left on device (os error 28)`. Garbage Collection und Prune lassen sich nicht starten, nicht einmal der Datastore lässt sich löschen. Liegt der Datastore auf dem Root-Dateisystem, funktioniert der ganze PBS nicht mehr richtig: keine Aufgaben, keine Statistiken, kein Systemlog.

**Warum:** ZFS schreibt jede Änderung neu (Copy-on-Write). Auch Löschen braucht deshalb etwas freien Platz. Die Garbage Collection des PBS setzt außerdem bei jedem benutzten Chunk die Zugriffszeit, und das ist ebenfalls ein Schreibvorgang.

<div class="warnung" id="bkmrk-auf-keinen-fall%3A-dat">**Auf keinen Fall:**- Dateien in `.chunks/` von Hand löschen. Chunks werden über alle Backups hinweg geteilt, damit machst du beliebige Backups kaputt.
- Zum Überbrücken mit `zpool add` eine Platte anhängen. Bei RAIDZ lässt sie sich nie wieder entfernen.
- Den Datastore löschen, solange es noch einen anderen Weg gibt.

</div>## 1. Lage erfassen (nur lesen)

```
zpool list
zfs list -o space
zfs list -t snapshot
df -h /
cat /etc/proxmox-backup/datastore.cfg          # wo liegt der Datastore (path)?
cat /etc/proxmox-backup/prune.cfg
cat /PFAD-ZUM-DATASTORE/.gc-status             # letzte GC: "pending-bytes" = wartet aufs Löschen
cat /sys/module/zfs/parameters/spa_slop_shift  # meist 5
```

Darauf achten:

- Liegt der Datastore auf dem System-Pool (`rpool`, Pfad wie `/backup` auf `/`)?
- Gibt es einen ungenutzten Pool?
- Wie hoch ist `pending-bytes` in `.gc-status`? So viel gibt die nächste erfolgreiche GC ohne weiteres Zutun frei.
- Wann sind die neuesten Backups (`ls /PFAD/vm/*/ | tail`)? Ein voller Speicher fällt oft erst nach Wochen auf.

## 2. Luft schaffen: ZFS-Reserve vorübergehend verkleinern

ZFS hält etwa 1/2<sup>spa\_slop\_shift</sup> des Pools zurück, beim Standardwert 5 also 1/32. Ein höherer Wert verkleinert diese Reserve und gibt sofort Platz frei. Die Änderung gilt nur bis zum nächsten Neustart.

```
echo 8 > /sys/module/zfs/parameters/spa_slop_shift   # Reserve 1/256 statt 1/32
df -h /                                               # sollte jetzt Platz zeigen
```

Beispiel: Bei einem Pool mit 2,9 TB wurden so 70 GB frei.

Gibt es ZFS-Snapshots auf dem Pool, sind sie die zweite schnelle Quelle für Platz (`zfs destroy pool/dataset@snap`, nur nach Prüfung). Auf `rpool` helfen außerdem `journalctl --vacuum-size=100M` und `apt clean`.

## 3. Garbage Collection laufen lassen

```
nohup proxmox-backup-manager garbage-collection start DATASTORE > /root/gc_$(date +%Y%m%d_%H%M).log 2>&1 &
tail -f /root/gc_*.log
```

Die GC löscht alles, was in `pending-bytes` stand. Im Beispiel waren das 252 GB bei rund einer Million Chunks, in etwa 2 Minuten.

Danach die Reserve **sofort zurückstellen**:

```
echo 5 > /sys/module/zfs/parameters/spa_slop_shift
```

## 4. Aufbewahrung herunterstellen und Prune ausführen

Neue Keep-Regeln setzen (siehe Anleitung „Aufbewahrung und Zeitpläne“). Vorher mit dem Probelauf (`--dry-run`) prüfen, was wegfallen würde. Dann:

```
proxmox-backup-manager prune-job update JOB-ID --keep-hourly 12 --keep-daily 14 --keep-weekly 4 \
  --delete keep-monthly --delete keep-yearly
proxmox-backup-manager prune-job run JOB-ID
```

Prune entscheidet nur, welche Backups wegfallen. Den Platz gibt erst die nächste GC frei, und dabei gibt es einen Haken:

## 5. Die 24-Stunden-Schutzfrist der GC

Die GC löscht nur Chunks, deren Zugriffszeit älter als **24 Stunden und 5 Minuten** ist. Hat eine GC die Chunks gerade erst angefasst (Schritt 3), bleiben die Chunks, die der Prune freigegeben hat, einen Tag lang stehen. Die GC meldet dann `Removed garbage: 0 B` und `Pending removals: … GiB`.

**Vorziehen (ab PBS 3.4):** Die Schutzfrist lässt sich pro Datastore kurz verkürzen.

<div class="warnung" id="bkmrk-die-schutzfrist-bewa">Die Schutzfrist bewahrt die Chunks **gerade laufender Backups**, deren Index noch nicht geschrieben ist. Läuft während einer GC mit verkürzter Frist ein Backup, kann *dieses* Backup kaputtgehen. Deshalb: vorher prüfen, dass keine Aufgabe läuft, und sicherstellen, dass in den nächsten Minuten kein Backup-Job startet.</div>```
cat /var/log/proxmox-backup/tasks/active                      # muss leer sein
proxmox-backup-manager datastore update DATASTORE --tuning 'gc-atime-cutoff=10'   # 10 Minuten
proxmox-backup-manager garbage-collection start DATASTORE
proxmox-backup-manager datastore update DATASTORE --delete tuning                 # ZURÜCK auf Standard!
```

Im Beispiel wurden dadurch sofort weitere 331 GiB frei. Die Belegung fiel von 100 % auf 80 %.

## 6. Danach

- **Backups wieder anwerfen.** Prüfen, ob die Jobs im PVE aktiviert sind. Einmal „Run now“, dann kontrollieren, ob alle VMs ankommen. VMs, die zwischendurch dazukamen, haben oft noch nie ein Backup.
- **Verify über alles laufen lassen.** Prüfungen, die bei vollem Speicher liefen, sind oft als fehlgeschlagen markiert.
- **Zeitpläne entzerren:** Backups, dann Prune (01:00), dann GC (02:00).
- **Überwachung einrichten:** eine Mail bei fehlgeschlagenem Backup und eine Warnung ab 80 % Belegung.
- **Strukturell:** Liegt der Datastore auf dem System-Pool, kann ein voller Datastore den ganzen PBS lahmlegen. Wenn möglich, gehört der Datastore auf einen eigenen Pool oder ein eigenes Dataset mit `quota`, damit für das System immer Platz bleibt: ```
    zfs create -o quota=2.5T rpool/pbs-store   # Beispiel: Datastore begrenzt, System behält Luft
    ```

## Kurzfassung

1. `echo 8 > /sys/module/zfs/parameters/spa_slop_shift`
2. `proxmox-backup-manager garbage-collection start DATASTORE`
3. `echo 5 > /sys/module/zfs/parameters/spa_slop_shift`
4. Keep-Regeln senken, Probelauf, Prune ausführen
5. Optional mit Vorsicht: `gc-atime-cutoff` kurz senken, GC, Tuning wieder löschen
6. Backups, Verify, Zeitpläne und Überwachung kontrollieren