TL; DR-Zusammenfassung : Übersetzen Sie eine MD-Sektornummer in Offsets innerhalb des /dev/mdX
Geräts und wie Sie sie untersuchen xfs_db
. Die Sektornummer ist von sh->sector
in linux/drivers/md/raid5.c:handle_parity_checks5()
.
Ich kenne keine MD-Interna, daher weiß ich nicht genau, was ich mit der Ausgabe der von printk
mir hinzugefügten Protokollierung tun soll .
dd
Interessant wären auch Offsets in die Komponentengeräte (für oder einen Hex-Editor / Viewer).
Ich nehme an, ich sollte dies auf der Linux-Raid-Mailingliste fragen. Ist es nur für Abonnenten oder kann ich ohne Abonnement posten?
Ich habe xfs direkt auf MD RAID5 von 4 Festplatten in meinem Desktop (kein LVM). Bei einem kürzlich durchgeführten Scrub wurde ein mismatch_cnt
Wert ungleich Null festgestellt (8 in der Tat, da md jeweils 4 KB-Seiten bearbeitet).
Dies ist ein RAID5, nicht RAID1 / RAID10, wobei mismatch_cnt
! = 0 während des normalen Betriebs auftreten kann . (Die anderen Links am Ende dieser Wiki-Seite können für einige Leute nützlich sein.)
Ich könnte nur blind sein repair
, aber dann hätte ich keine Ahnung, welche Datei auf mögliche Beschädigungen überprüft werden soll, abgesehen davon, dass ich keine Chance mehr habe, den Weg für die Rekonstruktion zu wählen. Die Antwort von Frostschutz auf eine ähnliche Frage ist der einzige Vorschlag, den ich gefunden habe, um einen Unterschied im Dateisystem festzustellen. Es ist umständlich und langsam, und ich würde lieber etwas Besseres verwenden, um es zuerst auf ein paar Dateien einzugrenzen.
Kernel-Patch zum Hinzufügen der Protokollierung
Seltsamerweise meldet die Überprüfungsfunktion von md nicht, wo ein Fehler gefunden wurde . Ich fügte hinzu , eine printk
in md / raid5.c einzuloggen sh->sector
im if
Zweig dass Schritte mddev->resync_mismatches
inhandle_parity_checks5()
(kleiner Patch auf GitHub veröffentlicht , ursprünglich basierend auf 4,5-rc4 von kernel.org.) Für diese für die allgemeinen Gebrauch in Ordnung zu sein, ist es wahrscheinlich brauchen würde Vermeiden Sie es, die Protokolle bei Reparaturen mit vielen Fehlanpassungen zu überfluten (möglicherweise nur, wenn der neue Wert resync_mismatches
<1000 ist?). Auch vielleicht nur anmelden check
und nicht repair
.
Ich bin mir ziemlich sicher, dass ich etwas Nützliches protokolliere (obwohl ich keine MD-Interna kenne!), Da dieselbe Funktion diese Sektornummer im Fehlerbehandlungsfall desswitch
druckt .
Ich habe meinen modifizierten Kernel kompiliert und gebootet und dann die Prüfung erneut ausgeführt:
[ 399.957203] md: data-check of RAID array md125
...
[ 399.957215] md: using 128k window, over a total of 2441757696k.
...
[21369.258985] md/raid:md125: check found mismatch at sector 4294708224 <-- custom log message
[25667.351869] md: md125: data-check done.
Jetzt weiß ich nicht genau, was ich mit dieser Sektornummer anfangen soll. Ist sh->sector * 512
eine lineare Adresse drin /dev/md/t-r5
(aka /dev/md125
)? Handelt es sich um eine Sektornummer in jedem Komponentengerät (bezieht sich also auf drei Daten und einen Paritätssektor)? Ich vermute letzteres, da eine Paritätsfehlanpassung in RAID5 bedeutet, dass N-1-Sektoren des md-Geräts in Gefahr sind und durch die Streifeneinheit gegeneinander versetzt sind. Ist Sektor 0 der Anfang des Komponentengeräts oder der Sektor nach dem Superblock oder so? Gab es weitere Informationen handle_parity_checks5()
, die ich hätte berechnen / protokollieren sollen?
Wenn ich nur die nicht übereinstimmenden Blöcke erhalten wollte, ist das richtig?
dd if=/dev/sda6 of=mmblock.0 bs=512 count=8 skip=4294708224
dd if=/dev/sdb6 of=mmblock.1 bs=512 count=8 skip=4294708224
dd if=/dev/sda6 of=mmblock.2 bs=512 count=8 skip=4294708224
dd if=/dev/sdd of=mmblock.3 bs=512 count=8 skip=4294708224 ## not a typo: my 4th component is a smaller full-disk
# i.e.
sec_block() { for dev in {a,b,c}6 d; do dd if=/dev/sd"$dev" of="sec$1.$dev" skip="$1" bs=512 count=8;done; }; sec_block 123456
Ich vermute nicht, weil ich 4k Nullen von allen vier Schlachtzugskomponenten bekomme, und 0^0 == 0
das sollte also die richtige Parität sein, oder?
Ein anderer Ort, an dem die Verwendung von Sektoradressen in md erwähnt wurde, ist für sync_min
und sync_max
(in sysfs). Neil Brown auf der Linux-Raid-Liste als Antwort auf eine Frage zu einem ausgefallenen Laufwerk mit Sektornummern von hdrecover
, bei dem Neil die Vollplatten-Sektornummer als MD-Sektornummer verwendete. Das ist nicht richtig, oder? Wären md-Sektornummern nicht relativ zu den Komponentengeräten (in diesem Fall Partitionen), nicht zu dem vollständigen Gerät, zu dem die Partition gehört?
linearer Sektor zu XFS-Dateiname:
Bevor mir klar wurde, dass die md-Sektornummer wahrscheinlich für die Komponenten und nicht für das RAID-Gerät bestimmt war, habe ich versucht, sie schreibgeschützt zu verwenden xfs_db
:
Dave Chinners sehr kurzer Vorschlag, wie man herausfindet, wie XFS einen bestimmten Block verwendet, schien für mich überhaupt nicht zu funktionieren. (Ich hätte für einen Sektor ein Ergebnis erwartet, da die Anzahl nicht über das Ende des Geräts hinausgehen sollte, auch wenn es sich nicht um den nicht übereinstimmenden Sektor handelt.)
# xfs_db -r /dev/md/t-r5
xfs_db> convert daddr 4294708224 fsblock
0x29ad5e00 (699227648)
xfs_db> blockget -nv -b 699227648
xfs_db> blockuse -n # with or without -c 8
must run blockget first
huh? Was mache ich hier falsch? Ich denke, das sollte eine separate Frage sein. Ich werde dies durch einen Link ersetzen, wenn ich danach frage oder woanders eine Antwort auf diesen Teil finde.
Mein RAID5 ist im Wesentlichen inaktiv, ohne Schreibaktivität und mit minimalem noatime
Lesevorgang (und daher führen Lesevorgänge nicht zu Schreibvorgängen).
Zusätzliches Zeug zu meinem Setup, hier nichts Wichtiges
Viele meiner Dateien sind Video- oder andere komprimierte Daten, mit denen effektiv festgestellt werden kann, ob die Daten korrekt sind oder nicht (entweder interne Prüfsummen im Dateiformat oder nur fehlerfreie Dekodierung). Das würde diese schreibgeschützte Loopback-Methode praktikabel machen, sobald ich weiß, welche Datei überprüft werden soll. Ich wollte jedoch nicht für jede Datei im Dateisystem einen 4-Wege-Diff ausführen, um zuerst die Nichtübereinstimmung zu finden, wenn der Kernel beim Überprüfen über die erforderlichen Informationen verfügt und diese problemlos protokollieren kann.
my /proc/mdstat
für mein Bulk-Daten-Array:
md125 : active raid5 sdd[3] sda6[0] sdb6[1] sdc6[4]
7325273088 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
bitmap: 0/19 pages [0KB], 65536KB chunk
Es befindet sich auf Partitionen auf drei Toshiba 3-TB-Laufwerken und einem nicht partitionierten WD25EZRS-Green-Power-Laufwerk (langsam), das ich durch ein anderes Toshiba ersetze. ( mdadm --replace
Ich habe es online ohne Lücken in der Redundanz gemacht. Nach einer Kopie wurde mir klar, dass ich den RAID-Zustand vorher und nachher überprüfen sollte, um Probleme zu erkennen. Dann habe ich die Nichtübereinstimmung festgestellt. Möglicherweise gibt es sie schon lange , da ich vor fast einem Jahr einige Abstürze hatte, aber keine alten Protokolle habe und mdadm standardmäßig keine E-Mails darüber sendet (Ubuntu 15.10).
Meine anderen Dateisysteme befinden sich auf RAID10f2-Geräten, die aus früheren Partitionen auf den drei größeren Festplatten (und RAID0 für / var / tmp) erstellt wurden. Das RAID5 ist nur für die Massenspeicherung gedacht, nicht /home
oder /
.
Meine Laufwerke sind alle in Ordnung: Die Anzahl der SMART-Fehler beträgt 0 für alle fehlerhaften Blockzähler auf allen Laufwerken, und kurze + lange SMART-Selbsttests wurden bestanden.
Fast Duplikate dieser Frage, die keine Antworten haben:
- Welche Chunks stimmen in einem Linux-MD-Array nicht überein?
- http://www.spinics.net/lists/raid/msg49459.html
- MDADM mismatch_cnt> 0. Gibt es eine Möglichkeit, festzustellen, welche Blöcke nicht übereinstimmen?
- Andere Dinge sind bereits inline verknüpft, vor allem aber die schreibgeschützte Loopback-Idee von Frostschutz .
- Scrubben auf der Arch Wiki RAID-Seite
quelle
mdadm -E /dev/xxx
..damaged
oder so, anstatt nur zu wissen, dass wahrscheinlich irgendwo eine kaputte Datei vorhanden ist.Antworten:
TL; DR sh-> Sektor ist die Anzahl der Sektoren auf den physischen Datenträgern nach dem Start des Datenabschnitts
Installieren
Hier ist ein einfacher Testaufbau zur Veranschaulichung:
Holen Sie sich jetzt einen Block ungleich Null und überschreiben Sie ihn
Stellen Sie sicher, dass der dm / md-Cache geleert ist, indem Sie das Array stoppen / neu zusammensetzen, und überprüfen Sie:
Blockieren auf Datenträgern
Okay, also lassen Sie uns zuerst überprüfen, ob 16384 mit dem übereinstimmt, was wir geschrieben haben. Meine Razzia hat einen 512k Streifen so ich , dass ich ausgerichtet schrieb etwas dafür gesorgt , einfach zu passen zu sein, wir schrieb
1024*10240
also0xa00000
.Ihr Patch enthält die Informationen. Beachten Sie
16384
, dass die Daten nicht bei 0 beginnen:So
printf "%x\n" $(((4096+16384)*512))
heißt es0xa00000
auch. Gut.Block in md
Nun, um dahin zu gelangen, wo das am md-Ende ist, ist es tatsächlich einfacher: Es ist einfach die Position, die in Sektorzeiten angegeben wurde,
number_of_stripes
z. B. für mich habe ich 4 Festplatten (3 + 1), also 3 Streifen.Hier bedeutet es
16384*3*512
zB0x1800000
. Ich habe die Diskette ziemlich gut gefüllt, so dass es einfach ist, nur die Diskette zu lesen und nach 1k Nullen zu suchen:Block in xfs
Cool. Mal sehen, wo das jetzt in xfs ist.
16384*3
ist49152
(daddr nimmt Sektornummer):Sicherlich sind die Nullen in dieser Datei:
Wenn wir diese Datei überschreiben, werden die Nullen auch in / dev / raidme / rd0 mit dem richtigen Versatz entfernt (einfach mit einer anderen Datei überschreiben). Wenn Sie erneut in / dev / raidme / rd0 schreiben (stellen Sie sicher, dass Sie das Array stoppen / erneut starten), sind die Nullen zurück. Sieht gut aus.
Es gibt jedoch noch ein weiteres Problem: Wenn Ihre Stripe-Größe hier so groß ist wie meine (512 KB), müssen wir uns nicht mit einem einzelnen Block befassen, sondern mit 1,5 MB möglicher Daten, die beschädigt sind einzelne Datei, aber Sie müssen dies überprüfen, zurück in xfs_db. Denken Sie daran, Inode früher war 2052.
Ein Block hat hier eine Größe von 4096 Bytes (siehe
xfs_info
), also sind unsere 1,5 MB 384 Blöcke. Unser beschädigtes Segment ist Block 6144 bis 6528 - gut innerhalb des ersten Segments dieser Datei.Etwas anderes zu betrachten wäre, die Blöcke von Hand zu extrahieren und zu überprüfen, wo genau die Prüfsummen nicht übereinstimmen, was Ihnen hoffentlich 3 kleinere Stücke zum Betrachten gibt.
Zu guter Letzt bin ich selbst kein md-Entwickler, aber als ehemaliger mdadm raid5-Benutzer wäre ich ziemlich interessiert gewesen. Ich würde sagen, es ist definitiv die Mühe wert, es ein bisschen voranzutreiben. Die Bereinigung, die Sie erwähnt haben, könnte nützlich sein, und ich bin sicher, dass die Entwickler einige Kommentare haben werden, sobald Sie einen Patch einreichen, aber zum Teufel muss md ausführlicher über diese Fehler sein!
quelle
printf '%#x\n' $(( (259072+4294708224 )*512 ))
ist0x20000000000
das offensichtlich kein Zufall. (Das sind genau 2 TB. Ich vermute einige Shenanigans von Grub-Install oder einer Art MBR-Sache). Ich hätte das nicht bemerkt, wenn ich nur Offsets im MD-Gerät betrachtet hätte, um die betroffene Datei zu finden. (Übrigens, das%#x
Format fügt das0x
Präfix für Sie hinzu.)xfs_db
sagt nurmust run blockget first
, obwohl ich es gerade getan habe (genau wie ich es in der Frage gepostet habe), nachdem ich Ihrem Beispiel gefolgt bin. Auch wenn ichblockget -v -n -b 12884124672
ihm einen bestimmten Block gebe. Ich habe verwendetdd
undhexdump
festgestellt, dass es in diesem Block tatsächlich eine Nichtübereinstimmung gibt. Drei sind alle Null, und der vierte hat ein einzelnes Ein-Bit, das auf 1 kB in den 512k-Streifen gesetzt ist. (Sehr praktisch, dass ich keinen Weg finden musste, um tatsächlich XOR-Blöcke zu überprüfen, um die Redundanz zu überprüfen.)daddr
zuerst (vor dem Blockget) verwende, erhalte ich keine Fehlermeldung, nur überhaupt keine Ausgabe vonblockget -v -n
undblockuse -v -n
. Falls es darauf ankommt, ist mein xfsprogs 3.2.1ubuntu1 und ich verwende Linux 4.2.0-36-generic (nicht meinen gepatchten -rc-Kernel). Mein FS verwendetcrc=1 isize=512
,naming =version 2 bsize=4096 ascii-ci=0 ftype=1
find -exec xfs_bmap -vpl {} +
nach einer Datei suchen, die den bekannten Block enthält.