Ich möchte ein NAS mit mdadm für das RAID und btrfs für die Bitrot-Erkennung erstellen. Ich habe ein ziemlich einfaches Setup, das 3 1-TB-Festplatten mit mdadm zu einem RAID5 kombiniert, und dann noch btrfs darüber.
Ich weiß, dass mdadm Bitrot nicht reparieren kann. Es kann mir nur sagen, wenn es Unstimmigkeiten gibt, aber es weiß nicht, welche Daten korrekt und welche fehlerhaft sind. Wenn ich mdadm sage, mein md0 zu reparieren, nachdem ich Bitrot simuliert habe, erstellt es immer die Parität neu. Btrfs verwendet Prüfsummen, damit es weiß, welche Daten fehlerhaft sind, aber es kann die Daten nicht reparieren, da es die Parität nicht sehen kann.
Ich kann jedoch einen Btrfs-Scrub ausführen und das Syslog lesen, um den Offset der Daten zu erhalten, die nicht mit ihrer Prüfsumme übereinstimmen. Ich kann diesen Offset dann in eine Festplatte und einen Offset auf dieser Festplatte übersetzen, da ich den Datenstart-Offset von md0 (2048 * 512), die Blockgröße (512 KB) und das Layout (linkssymmetrisch) kenne. Das Layout bedeutet, dass in meiner ersten Schicht die Parität auf der dritten Festplatte liegt, in der zweiten Schicht auf der zweiten Festplatte und in der dritten Schicht auf der ersten Festplatte.
Durch Kombination all dieser Daten und einiger weiterer Kenntnisse über das Festplattenformat von btrfs kann ich genau berechnen, welcher Block welcher Festplatte fehlerhaft ist. Ich kann jedoch keine Möglichkeit finden, mdadm anzuweisen, diesen bestimmten Block zu reparieren.
Ich habe bereits ein Skript geschrieben, das die Parität und den fehlerhaften Block mit dem Befehl dd austauscht, dann eine Reparatur mit mdadm startet und sie dann wieder zurück austauscht, aber das ist keine gute Lösung und ich möchte wirklich, dass mdadm diesen Sektor als fehlerhaft markiert und ihn nicht erneut verwendet. Da er zu verrotten begann, ist die Wahrscheinlichkeit hoch, dass es das erneut tut.
Meine Frage ist:gibt es eine Möglichkeit, mdadm anzuweisen, einen einzelnen Block (der nicht die Parität ist) zu reparieren und möglicherweise sogar einen Festplattensektor als fehlerhaft zu markieren? Vielleicht wird dadurch ein Lese-E/A-Fehler verursacht?
(Und ich weiß, dass ZFS das alles alleine machen kann, aber ich möchte keinen ECC-Speicher verwenden)
Bearbeiten:DasFrage/Antwort dreht sich darum, warum btrfs RAID6 instabil ist und warum ZFS viel stabiler/nutzbarer ist. Das geht nicht auf meine Frage ein, wie man einen einzelnen, bekannten fehlerhaften Block mit mdadm repariert.
Antwort1
Ich kann mdadm nicht anweisen, diesen bestimmten Block zu reparieren.
Dies liegt daran, dass md bei einer stillen Datenbeschädigung nicht über genügend Informationen verfügt, um zu erkennen, welcher Block stillschweigend beschädigt ist.
Ich lade Sie ein, meineAntwort auf Frage Nr. 4 („Warum wird md
ein Gerät mit ungültigen Daten weiter verwendet?“) hier, in dem dies genauer erläutert wird.
Um die Sache für Ihr vorgeschlagenes Layout noch schlimmer zu machen,Wenn ein Paritätsblock unter einer stillen Datenbeschädigung leidet, kann die darüber liegende Btrfs-Schicht dies nicht sehen! Wenn eine Platte mit dem entsprechenden Datenblock ausfällt und Sie versuchen, sie zu ersetzen, verwendet md die beschädigte Parität und beschädigt Ihre Daten unwiederbringlich. Erst wenn diese Platte ausfällt, erkennt Btrfs die Beschädigung, aber Sie haben die Daten bereits verloren.
Dies liegt daran, dass md nicht aus Paritätsblöcken liest, es sei denn, das Array ist beeinträchtigt.
Gibt es also eine Möglichkeit, mdadm anzuweisen, einen einzelnen Block (der nicht die Parität ist) zu reparieren und möglicherweise sogar einen Festplattensektor als fehlerhaft zu markieren? Vielleicht wird dadurch ein Lese-E/A-Fehler verursacht?
Bei fehlerhaften Sektoren, die die Festplatte selbst erkannt hat, kann md problemlos damit umgehen, da der fehlerhafte Sektor für md identifiziert wird.
Technisch gesehen können Sie mit einen fehlerhaften Sektor erstellen hdparm --make-bad-sector
, aber woher wissen Sie, auf welcher Festplatte der Block von der stillen Datenbeschädigung betroffen ist?
Betrachten Sie dieses vereinfachte Beispiel:
Paritätsformel:PARITY = DATA_1 + DATA_2
+--------+--------+--------+
| DATA_1 | DATA_2 | PARITY |
+--------+--------+--------+
| 1 | 1 | 2 | # OK
+--------+--------+--------+
Lassen Sie uns nun jeden der Blöcke stillschweigend mit dem folgenden Wert beschädigen 3
:
+--------+--------+--------+
| DATA_1 | DATA_2 | PARITY |
+--------+--------+--------+
| 3 | 1 | 2 | # Integrity failed – Expected: PARITY = 4
| 1 | 3 | 2 | # Integrity failed – Expected: PARITY = 4
| 1 | 1 | 3 | # Integrity failed – Expected: PARITY = 2
+--------+--------+--------+
Wenn Sie nicht die erste Tabelle zum Nachschauen hätten, woher wüssten Sie dann, welcher Block beschädigt ist?
Sie können es nicht mit Sicherheit wissen.
Aus diesem Grund prüfen Btrfs und ZFS beide Blöcke. Das nimmt zwar etwas mehr Speicherplatz in Anspruch, aber diese zusätzlichen Informationen ermöglichen dem Speichersystem herauszufinden, welcher Block lügt.
AusJeff Bonwicks Blogartikel „RAID-Z“:
Wenn Sie einen RAID-Z-Block lesen, vergleicht ZFS ihn mit seiner Prüfsumme. Wenn die Datenträger nicht die richtige Antwort zurückgegeben haben, liest ZFS die Parität und führt dann eine kombinatorische Rekonstruktion durch, um herauszufinden, welcher Datenträger fehlerhafte Daten zurückgegeben hat.
Um dies mit Btrfs auf md zu tun, müssten Sie versuchen, jeden Block neu zu berechnen, bis die Prüfsumme in Btrfs übereinstimmt, ein zeitaufwändiger Prozess ohne einfache Schnittstelle für den Benutzer/das Skript.
Ich weiß, dass ZFS das alles alleine machen kann, aber ich möchte keinen ECC-Speicher verwenden
Weder ZFS noch Btrfs über md sind von ECC-Speicher abhängig oder kennen ihn überhaupt. ECC-Speicher erkennt nur stille Datenbeschädigungen im Speicher und ist daher speichersystemunabhängig.
Ich habe ZFS gegenüber Btrfs für RAID-5 und RAID-6 (analog zu ZFS RAID-Z bzw. RAID-Z2) bereits inBtrfs über mdadm raid6?UndGerät im MD-RAID ausfallen lassen, wenn ATA nicht mehr reagiert, ich möchte die Gelegenheit aber nutzen, um noch ein paar weitere Vorteile von ZFS hervorzuheben:
- Wenn ZFS eine stille Datenbeschädigung erkennt, wird diese automatisch und sofort vor Ort korrigiert, ohne dass ein menschliches Eingreifen erforderlich ist.
- Wenn Sie eine ganze Festplatte neu erstellen müssen, führt ZFS nur ein „Resilver“ der eigentlichen Daten durch, anstatt diese unnötigerweise über das gesamte Blockgerät auszuführen.
- ZFS ist eine Komplettlösung für logische Datenträger und Dateisysteme und daher weniger komplex zu verwalten als Btrfs auf md.
- RAID-Z und RAID-Z2 sind zuverlässig und stabil, im Gegensatz zu
- Btrfs auf md RAID-5/RAID-6, das nur Fehlererkennung für stillschweigend beschädigte Datenblöcke bietet (außerdem können stillschweigend beschädigte Paritätsblöcke unentdeckt bleiben, bis es zu spät ist) und keine einfache Möglichkeit zur Fehlerkorrektur bietet, und
- Btrfs RAID-5/RAID-6, das "enthält mehrere schwerwiegende Fehler, die zu Datenverlust führen können".
- Wenn ich eine ganze Festplatte mit ZFS RAID-Z2 unbemerkt beschädigen würde, würden überhaupt keine Daten verloren gehen, während bei md RAID-6Ich habe tatsächlich 455.681 Inodes verloren.
Antwort2
Ich habe einen Weg gefunden, einen Lesefehler für mdadm zu erzeugen.
Mit dmsetup können Sie logische Geräte aus Tabellen erstellen.
Geräte werden durch Laden einer Tabelle erstellt, die für jeden Sektor ein Ziel angibt (512 Bytes).
Aus:manpage
In diesen Tabellen können Sie Offsets angeben, die einen IO-Fehler zurückgeben sollen, zum Beispiel:
0 4096 linear /dev/sdb 0
4096 1 error
4097 2093055 linear /dev/sdb 4097
Dadurch wird ein Gerät (1 GB) mit einem Fehler beim Offset 4096 * 512 erstellt.