Login
Newsletter
Werbung

So, 27. August 2006, 00:00

Fehlerhafte Festplattensektoren neu zuweisen

Festplatten mit SMART lassen sich mit den smartmontools während des Betriebes überwachen und testen. Defekte Sektoren können diese Platten auch neu zuweisen. Das Ermitteln der Blöcke und der Dateien, die diese Blöcke verwenden, ist jedoch etwas umständlich. Mit Unterstützung eines Skriptes geht es zumindest für ext2 und ext3 recht flott.

Mit den smartmontools habe ich mit neueren IDE-Platten die Möglichkeit, defekte Blöcke im laufenden Betrieb zu erkennen und - wenn ich die Platte nicht wechseln kann oder will - durch andere Blöcke aus einem Reservebereich der Platte zu ersetzen.

Im Bad Block HowTo wird beschrieben, wie man die Datei identifiziert, die einen unlesbaren Festplattensektor benutzt, und wie man diesen Sektor zur Reallokation zwingt, vorausgesetzt, man hat Linux und ein ext2- oder ext3-Filesystem.

Die Anleitung ist recht ausführlich und zielführend. Aber spätestens ab dem zweiten Sektor hatte ich doch das Bedürfnis, mir die Sache etwas zu erleichtern. Also habe ich meinen Lieblingseditor veranlasst, #!/usr/bin/perl an den Anfang einer neuen Datei zu schreiben. Davon handelt dieser Artikel. Vorher komme ich für die, die oben genannten Text nicht gelesen haben, kurz zur Sache selbst, dem Neuzuweisen von defekten Plattensektoren. Im Wesentlichen läuft die Sache so ab:

  1. Ich stoße mit smartctl den Selbsttest der Platte an.
  2. Wenn der Selbsttest durchgelaufen ist - smartctl gibt dafür eine Schätzung an - schaue ich mir das Ergebnis des Selbsttests an und merke mir den ersten schlechten Block. Gibt es keinen, bin ich schon fertig.
  3. Ich ermittle mit fdisk die Partition und den Offset innerhalb der Partition, in der der Block liegt.
  4. Mit debugfs ermittle ich, ob eine Datei an dieser Stelle liegt, und wenn ja, welche.
  5. Mit dd beschreibe ich den Block und sorge mit sync dafür, dass diese Daten auch wirklich zur Platte geschickt werden.
  6. Ich starte wieder bei 1., um mich zu überzeugen, dass dieser Block nicht mehr verwendet wird, und um zu sehen, ob es noch mehr Fehler gibt.

Am Ende müssen die ermittelten und teilweise überschriebenen Dateien natürlich aus dem Backup wieder hergestellt werden.

Um das wenigstens teilweise zu automatisieren, muss ich in Perl die Ausgaben von fünf Programmen (smartctl, fdisk, mount, tune2fs, debugfs) auswerten und interpretieren. Eines davon (debugfs) möchte gern interaktiv bedient werden, das gibt einen Heidenspass. An die Arbeit.

Selbsttest der Platte anstoßen

Falls die Platte nicht regelmäßig Selbsttests macht, stoße ich einen mit smartctl -t offline /dev/hda an. Dieser Test läuft eine gewisse Zeit, solange muss ich warten. In meinem Beispiel gehe ich davon aus, dass die erste Festplatte am ersten Controller defekt ist, im Perl-Code steht das in der Variable $disk.

Ergebnis des Selbsttests auswerten und schlechten Block merken

Das Ergebnis des Selbsttests sehe ich mir mit smartctl -l selftest /dev/hda an. Die Ausgabe könnte ungefähr so aussehen:

smartctl version 5.32 Copyright (C) 2002-4 Bruce Allen
Home page is 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 without error 00% 26824 -
...
# 5 Short offline Completed without error 00% 26739 -
# 6 Extended offline Completed: read faulure 40% 26719 55908297
...

Smartctl gibt in Tabellenform die Nummer des Tests, eine Testbeschreibung, den Status, den »LBA_of_first_error« und noch mehr aus. Für mich interessant sind die »Extended offline«-Tests mit Status »Completed: read failure«. Von diesem Test nehme ich das Feld »LBA_of_first_error« (das letzte):

$disk = shift;
$smartctl_cmd = "smartctl -l selftest $disk";
open(SMART, "$smartctl_cmd|")
 or die "Error in smartctl: $!";
while (<SMART>) {
 if (m{ ^\#\s*\d+\s+
 Extended\ offline
 \s+
 Completed:
 \ read\ failure
 \s+\d+%\s+\d+\s+
 (\S+)
 \s*$
 }x) {
 $lba = $1;
 last;
 }
}
exit 0 unless (defined $lba);

Damit habe ich die gewünschte Blocknummer des ersten fehlerhaften Sektors in $lba. Zu diesem bestimme ich als nächstes die zugehörige Partition.

Partition und Offset des schlechten Blocks ermitteln

Um die Partition zu ermitteln, lasse ich mir alle mit fdisk -lu /dev/hda auflisten, suche die betroffene Partition heraus und berechne den Offset in die Partition. Wenn der fehlerhafte Block in einer logischen Partition innerhalb einer erweiterten Partition liegt, finde ich zwei Partitionen. Davon nehme ich die letzte.

$fdisk_cmd = "fdisk -lu $disk";
open(FDISK,"$fdisk_cmd|")
 or die "Error in fdisk: $!";
while (<FDISK>) {
 if (m{ ^($disk[0-9]+)
 \s+\*?\s+
 ([0-9]+)
 \s+
 ([0-9]+)
 \s+
 }x) {
 if ($2 <= $lba
 and $3 >= $lba) {
 $part = $1;
 $poffset = $lba - $2;
 }
 }
}
die "no partition found for $lba"
 unless (defined $part);

Nun habe ich den fehlerhaften Block in $lba, die Partition, in der er zu finden ist, in $part und den Offset vom Beginn der Partition in $poffset. Jetzt könnte ich den Block schon von der Platte ersetzen lassen und gut ist. Besser ist aber, erst nachzusehen, ob dieser Block eventuell zu einer Datei gehört.

Kommentare (Insgesamt: 0 )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung