Die Kurzfassung: Wie würde ich vorgehen, um einen fehlerhaften Block auf einer Festplatte in einem RAID1-Array zu reparieren?
Aber bitte lesen Sie das Ganze, um zu erfahren, was ich bereits versucht habe und welche Fehler in meinen Methoden möglich sind. Ich habe versucht, so detailliert wie möglich zu sein, und hoffe wirklich auf Feedback
Das ist meine Situation: Ich habe zwei 2TB-Festplatten (dasselbe Modell) in einem RAID1-Array eingerichtet, das von verwaltet wird mdadm
. Vor etwa 6 Monaten bemerkte ich den ersten fehlerhaften Block, als SMART ihn meldete. Heute sind mir weitere aufgefallen und ich versuche nun, das Problem zu beheben.
Diese HOWTO-Seitescheint der einzige Artikel zu sein, auf den alle verlinken, um fehlerhafte Blöcke zu beheben, die SMART meldet. Es ist eine großartige Seite voller Informationen, aber sie ist ziemlich veraltet und geht nicht auf mein spezielles Setup ein. So unterscheidet sich meine Konfiguration:
- Anstelle einer Festplatte verwende ich zwei Festplatten in einem RAID1-Array. Eine Festplatte meldet Fehler, während die andere einwandfrei funktioniert. Das HOWTO ist nur für eine Festplatte geschrieben, was verschiedene Fragen aufwirft, wie z. B. „Verwende ich diesen Befehl auf dem Festplattengerät oder dem RAID-Gerät?“
- Ich verwende GPT, das von fdisk nicht unterstützt wird. Stattdessen verwende ich gdisk und hoffe, dass es mir die gleichen Informationen liefert, die ich brauche.
Also, lasst uns zur Sache kommen. Das habe ich getan, aber es scheint nicht zu funktionieren. Bitte überprüfen Sie meine Berechnungen und meine Methode noch einmal auf Fehler. Die Festplatte, die Fehler meldet, ist /dev/sda:
# smartctl -l selftest /dev/sda
smartctl 5.42 2011-10-20 r3458 [x86_64-linux-3.4.4-2-ARCH] (local build)
Copyright (C) 2002-11 by Bruce Allen, http://smartmontools.sourceforge.net
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed: read failure 90% 12169 3212761936
Daraus können wir schließen, dass der Fehler bei LBA 3212761936 liegt. Gemäß dem HOWTO verwende ich gdisk, um den Startsektor zu finden, der später zur Ermittlung der Blocknummer verwendet wird (da ich fdisk nicht verwenden kann, da es GPT nicht unterstützt):
# gdisk -l /dev/sda
GPT fdisk (gdisk) version 0.8.5
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 3907029168 sectors, 1.8 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): CFB87C67-1993-4517-8301-76E16BBEA901
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)
Number Start (sector) End (sector) Size Code Name
1 2048 3907029134 1.8 TiB FD00 Linux RAID
Mithilfe von tunefs
ermittle ich, dass die Blockgröße 4096
. Anhand dieser Informationen und der Berechnung aus dem HOWTO komme ich zu dem Schluss, dass der betreffende Block . ist ((3212761936 - 2048) * 512) / 4096 = 401594986
.
Anschließend werde ich im HOWTO angewiesen, debugfs
zu prüfen, ob der Block verwendet wird (ich verwende das RAID-Gerät, da es ein EXT-Dateisystem benötigt. Dies war einer der Befehle, die mich verwirrt haben, da ich zunächst nicht wusste, ob ich /dev/sda oder /dev/md0 verwenden sollte):
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs: open /dev/md0
debugfs: testb 401594986
Block 401594986 not in use
Block 401594986 ist also leerer Speicherplatz, ich sollte ihn problemlos überschreiben können. Bevor ich ihn beschreibe, versuche ich jedoch sicherzustellen, dass er tatsächlich nicht gelesen werden kann:
# dd if=/dev/sda1 of=/dev/null bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000198887 s, 20.6 MB/s
Wenn der Block nicht gelesen werden könnte, würde ich nicht erwarten, dass dies funktioniert. Es funktioniert jedoch. Ich wiederhole die Verwendung von /dev/sda
, /dev/sda1
, /dev/sdb
, /dev/sdb1
, /dev/md0
, und +-5 zur Blocknummer, um um den fehlerhaften Block herum zu suchen. Es funktioniert alles. Ich zucke mit den Schultern und mache weiter und übergebe den Schreib- und Synchronisierungsvorgang (ich verwende /dev/md0, weil ich dachte, dass das Ändern einer Festplatte und nicht der anderen Probleme verursachen könnte. Auf diese Weise überschreiben beide Festplatten den fehlerhaften Block):
# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000142366 s, 28.8 MB/s
# sync
Ich würde erwarten, dass beim Schreiben in den fehlerhaften Block die Festplatten den Block einem fehlerfreien neu zuweisen würden. Das Ausführen eines weiteren SMART-Tests zeigt jedoch etwas anderes:
# 1 Short offline Completed: read failure 90% 12170 3212761936
Zurück zum Ausgangspunkt. Wie würde ich also grundsätzlich einen fehlerhaften Block auf einer Festplatte in einem RAID1-Array reparieren? Ich bin sicher, dass ich etwas nicht richtig gemacht habe ...
Vielen Dank für Ihre Zeit und Geduld.
BEARBEITEN 1:
Ich habe versucht, einen langen SMART-Test auszuführen, bei dem derselbe LBA als „schlecht“ zurückgegeben wurde (der einzige Unterschied besteht darin, dass 30 % verbleibend statt 90 % gemeldet werden):
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed: read failure 30% 12180 3212761936
# 2 Short offline Completed: read failure 90% 12170 3212761936
Ich habe auch Badblocks mit der folgenden Ausgabe verwendet. Die Ausgabe ist seltsam und scheint falsch formatiert zu sein, aber ich habe versucht, die als Blöcke ausgegebenen Zahlen zu testen, aber debugfs gibt einen Fehler aus
# badblocks -sv /dev/sda
Checking blocks 0 to 1953514583
Checking for bad blocks (read-only test): 1606380968ne, 3:57:08 elapsed. (0/0/0 errors)
1606380969ne, 3:57:39 elapsed. (1/0/0 errors)
1606380970ne, 3:58:11 elapsed. (2/0/0 errors)
1606380971ne, 3:58:43 elapsed. (3/0/0 errors)
done
Pass completed, 4 bad blocks found. (4/0/0 errors)
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs: open /dev/md0
debugfs: testb 1606380968
Illegal block number passed to ext2fs_test_block_bitmap #1606380968 for block bitmap for /dev/md0
Block 1606380968 not in use
Ich weiß nicht genau, wie es jetzt weitergehen soll. Ich badblocks
habe definitiv etwas gefunden, bin mir aber nicht sicher, was ich mit den angezeigten Informationen anfangen soll ...
BEARBEITEN 2
Weitere Befehle und Informationen.
Ich komme mir wie ein Idiot vor, weil ich vergessen habe, dies ursprünglich einzuschließen. Dies sind SMART-Werte für /dev/sda
. Ich habe 1 Current_Pending_Sector und 0 Offline_Uncorrectable.
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
1 Raw_Read_Error_Rate 0x002f 100 100 051 Pre-fail Always - 166
2 Throughput_Performance 0x0026 055 055 000 Old_age Always - 18345
3 Spin_Up_Time 0x0023 084 068 025 Pre-fail Always - 5078
4 Start_Stop_Count 0x0032 100 100 000 Old_age Always - 75
5 Reallocated_Sector_Ct 0x0033 252 252 010 Pre-fail Always - 0
7 Seek_Error_Rate 0x002e 252 252 051 Old_age Always - 0
8 Seek_Time_Performance 0x0024 252 252 015 Old_age Offline - 0
9 Power_On_Hours 0x0032 100 100 000 Old_age Always - 12224
10 Spin_Retry_Count 0x0032 252 252 051 Old_age Always - 0
11 Calibration_Retry_Count 0x0032 252 252 000 Old_age Always - 0
12 Power_Cycle_Count 0x0032 100 100 000 Old_age Always - 75
181 Program_Fail_Cnt_Total 0x0022 100 100 000 Old_age Always - 1646911
191 G-Sense_Error_Rate 0x0022 100 100 000 Old_age Always - 12
192 Power-Off_Retract_Count 0x0022 252 252 000 Old_age Always - 0
194 Temperature_Celsius 0x0002 064 059 000 Old_age Always - 36 (Min/Max 22/41)
195 Hardware_ECC_Recovered 0x003a 100 100 000 Old_age Always - 0
196 Reallocated_Event_Count 0x0032 252 252 000 Old_age Always - 0
197 Current_Pending_Sector 0x0032 100 100 000 Old_age Always - 1
198 Offline_Uncorrectable 0x0030 252 100 000 Old_age Offline - 0
199 UDMA_CRC_Error_Count 0x0036 200 200 000 Old_age Always - 0
200 Multi_Zone_Error_Rate 0x002a 100 100 000 Old_age Always - 30
223 Load_Retry_Count 0x0032 252 252 000 Old_age Always - 0
225 Load_Cycle_Count 0x0032 100 100 000 Old_age Always - 77
# mdadm -D /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Thu May 5 06:30:21 2011
Raid Level : raid1
Array Size : 1953512383 (1863.01 GiB 2000.40 GB)
Used Dev Size : 1953512383 (1863.01 GiB 2000.40 GB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Update Time : Tue Jul 3 22:15:51 2012
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0
Name : server:0 (local to host server)
UUID : e7ebaefd:e05c9d6e:3b558391:9b131afb
Events : 67889
Number Major Minor RaidDevice State
2 8 1 0 active sync /dev/sda1
1 8 17 1 active sync /dev/sdb1
Laut einer der Antworten: Es scheint, als hätte ich zwischen seek
und skip
für gewechselt dd
. Ich habe seek verwendet, da dies im HOWTO verwendet wird. Die Verwendung dieses Befehls führt dd
zum Hängenbleiben: # dd if=/dev/sda1 of=/dev/null bs=4096 count=1 skip=401594986
Die Verwendung von Blöcken um diesen herum (..84, ..85, ..87, ..88) scheint einwandfrei zu funktionieren, und die Verwendung von /dev/sdb1 mit Blocklesevorgängen funktioniert 401594986
ebenfalls einwandfrei (wie erwartet, da diese Festplatte den SMART-Test bestanden hat). Nun ist meine Frage: Wenn ich über diesen Bereich schreibe, um die Blöcke neu zuzuweisen, verwende ich dann /dev/sda1
oder /dev/md0
? Ich möchte keine Probleme mit dem RAID-Array verursachen, indem ich direkt auf eine Festplatte schreibe und die andere Festplatte nicht aktualisiere.
BEARBEITEN 3
Das Schreiben in den Block führte direkt zu Dateisystemfehlern. Ich habe eine Antwort gewählt, die das Problem schnell löste:
# 1 Short offline Completed without error 00% 14211 -
# 2 Extended offline Completed: read failure 30% 12244 3212761936
Danke an alle die mitgeholfen haben. =)
Antwort1
Alle diese „Sektor anstupsen“-Antworten sind, offen gesagt, verrückt. Sie riskieren eine (möglicherweise versteckte) Beschädigung des Dateisystems. Wenn die Daten bereits weg wären, weil auf dieser Festplatte die einzige Kopie gespeichert ist, wäre das vernünftig. Aber auf dem Spiegel befindet sich eine vollkommen gute Kopie.
Sie müssen nur mdraid den Spiegel bereinigen lassen. Es erkennt den fehlerhaften Sektor und schreibt ihn automatisch neu.
# echo 'check' > /sys/block/mdX/md/sync_action # use 'repair' instead for older kernels
Sie müssen dort das richtige Gerät eingeben (z. B. md0 statt mdX). Dies dauert eine Weile, da standardmäßig das gesamte Array ausgeführt wird. Auf einem ausreichend neuen Kernel können Sie zuerst Sektornummern in sync_min/sync_max schreiben, um es auf nur einen Teil des Arrays zu beschränken.
Dies ist ein sicherer Vorgang. Sie können ihn auf allen Ihren mdraid-Geräten durchführen. TatsächlichsollenFühren Sie dies regelmäßig auf allen Ihren mdraid-Geräten durch. Ihre Distribution wird wahrscheinlich mit einem Cronjob ausgeliefert, der dies handhabt. Vielleicht müssen Sie etwas tun, um ihn zu aktivieren?
Skript für alle RAID-Geräte im System
Vor einiger Zeit habe ich dieses Skript geschrieben, um alle RAID-Geräte im System zu „reparieren“. Es wurde für ältere Kernel-Versionen geschrieben, bei denen nur „Reparieren“ den fehlerhaften Sektor reparieren konnte; jetzt reicht es aus, einfach „check“ auszuführen (das Reparieren funktioniert bei neueren Kerneln immer noch einwandfrei, aber es kopiert/rekonstruiert auch die Parität neu, was nicht immer erwünscht ist, insbesondere bei Flash-Laufwerken).
#!/bin/bash
save="$(tput sc)";
clear="$(tput rc)$(tput el)";
for sync in /sys/block/md*/md/sync_action; do
md="$(echo "$sync" | cut -d/ -f4)"
cmpl="/sys/block/$md/md/sync_completed"
# check current state and get it repairing.
read current < "$sync"
case "$current" in
idle)
echo 'repair' > "$sync"
true
;;
repair)
echo "WARNING: $md already repairing"
;;
check)
echo "WARNING: $md checking, aborting check and starting repair"
echo 'idle' > "$sync"
echo 'repair' > "$sync"
;;
*)
echo "ERROR: $md in unknown state $current. ABORT."
exit 1
;;
esac
echo -n "Repair $md...$save" >&2
read current < "$sync"
while [ "$current" != "idle" ]; do
read stat < "$cmpl"
echo -n "$clear $stat" >&2
sleep 1
read current < "$sync"
done
echo "$clear done." >&2;
done
for dev in /dev/sd?; do
echo "Starting offline data collection for $dev."
smartctl -t offline "$dev"
done
check
Wenn Sie anstelle von Folgendes tun möchten repair
, sollte dieser (ungetestete) erste Block funktionieren:
case "$current" in
idle)
echo 'check' > "$sync"
true
;;
repair|check)
echo "NOTE: $md $current already in progress."
;;
*)
echo "ERROR: $md in unknown state $current. ABORT."
exit 1
;;
esac
Antwort2
Ich hatte gerade so ziemlich das gleiche Problem mit einem RAID1-Array. Der fehlerhafte Sektor befand sich direkt am Anfang einer der Partitionen – Sektor 16 von /dev/sdb2. Ich folgte den obigen Anweisungen: Nachdem ich überprüft hatte, dass der logische Block 2 nicht vom Dateisystem verwendet wurde, und darauf geachtet hatte, dass DD Seek und Skip in der richtigen Reihenfolge ausgeführt wurden, setzte ich einen Dateisystemblock auf Null:
# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=2
Was hat das bewirkt? Der fehlerhafte Sektor wurde nicht repariert. Das liegt, wie ich jetzt weiß, daran, dass /dev/md0 nicht direkt auf /dev/sdb2 abgebildet wird, man muss den RAID-DATENOFFSET berücksichtigen! Mehr dazu weiter unten. Was es bewirkt hat, war ein kleiner, aber potenziell verheerender Haufen Mist auf meinem Dateisystem. Es stellte sich heraus, dass der logische Block 2 von /dev/md0 nützliche Dateisystemmetadaten enthielt und auf beiden Festplatten in Ordnung war, bis ichbeideKopien durch Schreiben in /dev/md0. Glücklicherweise hat e2fsck -y /dev/md0 das Problem behoben (nachdem es eine alarmierende Menge an Ausgabe ausgegeben hatte), ohne dass es zu sichtbarem Datenverlust kam. Lektion gelernt: Wenn debugfs icheck „Block nicht gefunden“ anzeigt, bedeutet das nicht unbedingt, dass die entsprechenden Sektoren nicht verwendet werden.
Zurück zum Datenoffset: Verwenden Sie mdadm, um den Offset wie folgt zu finden:
# mdadm --examine /dev/sdb2
/dev/sdb2:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : ef7934b9:24696df9:b89ff03e:b4e5a05b
Name : XXXXXXXX
Creation Time : Sat Sep 1 01:20:22 2012
Raid Level : raid1
Raid Devices : 2
Avail Dev Size : 1953241856 (931.38 GiB 1000.06 GB)
Array Size : 976620736 (931.38 GiB 1000.06 GB)
Used Dev Size : 1953241472 (931.38 GiB 1000.06 GB)
Data Offset : 262144 sectors
Super Offset : 8 sectors
State : clean
Device UUID : f3b5d515:446d4225:c2191fa0:9a9847b8
Update Time : Thu Sep 6 12:11:24 2012
Checksum : abb47d8b - correct
Events : 54
Device Role : Active device 0
Array State : AA ('A' == active, '.' == missing)
In diesem Fall beträgt der Datenoffset 262144 Sektoren mit je 512 Bytes. Wenn Sie von /dev/md0 aus dd ausführen und es mit Daten aus der Rohpartition mit einem Offset von 131072K vergleichen, werden Sie feststellen, dass sie übereinstimmen. In meinem Fall befindet sich der logische Block 2 (Sektoren 16-23) von /dev/sdb2 also nicht einmal im Dateisystem; er befindet sich im RAID-Superblock, über den Sie hier mehr erfahren können: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats- für Version 1.2 besteht es aus 256 Bytes + 2 Bytes pro Gerät im Array, alles beginnend bei 4096 Bytes, also wurde in meinem Fall der fehlerhafte Sektor nicht verwendet. Die entsprechenden Sektoren von /dev/sdc2 (die andere Hälfte des RAID1-Arrays) sind Null, also dachte ich, es wäre sicher, dies zu tun:
# dd if=/dev/zero of=/dev/sdb2 bs=4096 count=1 seek=2
Es funktionierte!
Antwort3
Wenn Sie Debian verwenden, haben Sie höchstwahrscheinlich einen Job in /etc/cron.d/mdadm . Dieser wird /usr/share/mdadm/checkarray --cron --all --idle --quiet
jeden ersten Sonntag im Monat ausgeführt. Führen Sie ihn manuell aus, wenn Sie nicht korrigierbare Hardwarefehler erhalten, um das Neuschreiben zu beschleunigen.
Antwort4
Wenn Sie ein sw-raid1 haben und Daten direkt auf eines der Mitglieder schreiben, wird Ihr Raid sofort beschädigt. Schreiben Sie KEINE Daten auf ein sdaX oder sdbX, wenn diese Teil eines mdX sind. Wenn Sie auf mdX schreiben, werden die Daten auf beide Laufwerke kopiert, wenn Sie von mdX lesen, werden die Daten von einem der Laufwerke gelesen.