If you need an English translation of this little HOWTO, give me a shout at are@lihas.de
* Linux Softwareraid RAID-1 mit 2 Platten, auf den Platten waren die Daten in LVM-Partitionen. * Die Platten wurden zu klein und deshalb sollte das RAID-1 online in ein RAID-5 mit 3 Platten umgerechnet werden mittels 'mdadm --grow' * Leider war die neue Platte defekt, d.h. die Datenübertragung ging extrem langsam, aber ohne Fehler und schliesslich blieb der ganze Rechner stehen. * Das / Verzeichnis war ein LVM, installiert war ein Debian Squeeze mit selbst kompiliertem 2.6.35er Kernel
* Die Platte war super langsam (1.2KB/s-1.2MB/s), es konnten noch nicht viele Daten wirklich weg sein * Am Anfang der Platte waren 8GB swap als Logical Volume (LV) angelegt, am Ende der Platte waren noch einige GB Platz. Damit müssen die Daten, egal ob von vorne oder hinten umgerechnet wird, vorhanden sein.
* Es war unklar, welche Art RAID Superblock für das RAID-1 verwendet wurde und damit an welcher Stelle das Physical Volume (PV) tatächlich beginnt * Es existierte kein Backup der LVM Metadaten * Programme zur Partitionswiederherstellung kommen nicht mit LVM an sich klar und bestehen auf (C/H/S) Adressierungen
* Um den Rücken frei zu haben habe ich auf andere Platten ein Debian Squeeze mit 2.6.32er Kernel installiert, ein Rescue-System geht prinzipiell auch, allerdings ging es hier um 2TB Daten und ich habe das Recovery größtenteils via ssh durchgeführt und während meiner Versuche ab und zu mal neu gestartet * Erstellen eines neuen RAID-1 als /dev/md9 auf einer der ehemaligen Platten, diese läuft bei mir als /dev/sdd, die andere Platte habe ich mal in Ruhe gelassen, nicht unbedingt notwendig, ich hatte mir allerdings erhofft dann einfacher an die wirklichen Startbloecke des LVM zu kommen: * mdadm -C -l1 -n2 -x0 /dev/md9 /dev/sdd2 missing * Einlesen der ersten paar Sektoren um die LVM-Informationen zurück zu gewinnen (http://www.linuxjournal.com/article/8874?page=0,1): * dd if=/dev/sdd2 bs=512 count=255 skip=1 of=/root/rescue-md2-start.dd * vi /root/rescue-md2-start.dd * von Hand nach LVM-Metadaten Ausschau halten und die gefühlt neuste Version sichern, in meinem Fall war die Info für 'root2', meinem alten / besonders wichtig. Darauf findet sich das normale Backup der echten Metadaten unter /etc/lvm/backup. Diese Partition habe ich auch nie vergrößert und die ist deshalb am Stück. Das erleichtert das weitere Vorgehen. * testdisk Einsatz auf /dev/md9. testdisk arbeitet auf Zylinderebene, lässt sich aber auf Sektoren umstellen. Ich habe außerdem als Geometrie 4 Sektoren, 2 Köpfe und dann eben die resultierenden Zylinder angegeben. Das führt zu einer für mich leichteren Umrechnung auf Sektoren. Die testdisk Ausgabe mit den gefundenen 'Partitionen' habe ich von Hand in eine Datei kopiert. Das ist unschön, allerdings hat sich das testdisk bei jeglichem weiterführenden Menütastendruck verabschiedet. 8500 verschiedene Partitionen sind für ein Programm, das sich mit DOS Disklabels beschäftigt wohl etwas viel. Ich hatte natürlich keine 8500 Logical Volums (LVs) auf dem System, allerdings werden die Partition sehr häufig gefunden. Dass die meisten meiner Dateisysteme mit einem Label versehen waren, hat die Identifizierung sehr erleichtert. Mein root-Dateisystem hatte so das Tag [root2]. Im ersten Ansatz habe ich einfach die erste Partition mit dem passenden Tag genommen, das hat auch gut funktioniert. Um damit was anfangen zu können, muss das von (C/H/S) in Sektoren oder Byte umgerechnet werden: * Sektoren: =((C*2*4)+(H*4)+S+1) * Byte: Sektoren von oben * 512 * Recovery der LVM-Daten * Ich habe ext4 verwendet, da das System hart ausgeschaltet wurde, muss das Journal nachgezogen werden. Dazu wird Schreibzugriff benötigt, der Squeeze 2.6.32er Kernel erlaubt das nicht für Loopbackmounts von Device-Ausschnitten, deshalb habe ich mir ein Image der Daten gezogen: * Testdisk Ausgabe:
TestDisk 6.11, Data Recovery Utility, April 2009 Christophe GRENIER <grenier@cgsecurity.org> http://www.cgsecurity.org Disk /dev/md1 - 2000 GB / 1862 GiB - CHS 488311712 2 4 Partition Start End Size in sectors P Linux LVM2 0 0 1 488311711 1 4 3906493696 P ext4 80 1 3 2621520 1 2 20971520 P Linux SWAP 2 81 0 1 2097230 1 4 16777200 P ext4 81 0 1 2621520 1 4 20971520 P ext4 2097232 1 3 4718672 1 2 20971520 [root] P ext4 2097233 0 1 4718672 1 4 20971520 [root] P FAT12 2283089 0 1 2283448 1 4 2880 [BOOT622] P FAT12 2283601 0 1 2283960 1 4 2880 [BOOT622] ... P ext4 3211338 0 1 5832777 1 4 20971520 P FAT12 3499767 1 1 3500127 0 4 2880 [dban-1.0.7] P FAT12 4239029 0 4 4239389 0 3 2880 [NO NAME] P FAT12 4239825 0 4 4240185 0 3 2880 [NO NAME] P HFS 4349924 0 3 372082214 1 3 2941858325 [^B~?^WI/^RM-@~T^B DeM-J^D~_7:^P^AM-@t~J^R^^] P ext4 4718672 1 3 135790672 1 2 1048576000 [mythtv] P ext4 4718673 0 1 135790672 1 4 1048576000 [mythtv] ^D0^E^CG^B~?^[ ~Z] 18861385 0 3 90510564 0 1 573193431 [^PZ
* Resultierender Sektor: 2097232*4 + 1*4 + 3 + 1 = 16777864 * Resultierendes dd: dd if=/dev/md9 bs=512 skip=16777864 count=20971520 of=root.dd * fsck.ext4 root.dd * mount -o loop,noatime,barrier=0,nobh,commit=100 root.dd /mnt * Daten kopieren, z.B. mit rsync * war nur zum Üben, das Label 'root' ist eine alte Version von einer Migration. Ich habe dann noch mit anderen Dateisystemen geübt. * Mein 2.6.35er Kernel kann auch direkt mit dem Loopmount auf das Device und den Journal recovern, da werden dann die Byte benötigt, spart das 'dd' für Partitionen die am Stück sind: * mount -o loop,noatime,barrier=0,nobh,commit=100,offset=$((16777864*512)) /dev/md9 /mnt * Aus den (C/H/S), bzw. Sektoren lässt sich dann der wirkliche Offset der LVM-Daten auf dem PV mit Hilfe der wieder gewonnenen LVM Metadaten errechnen:
vg_bofh { id = "cyMmsn-S77F-qwVg-xzqm-Q7U6-G8PB-CkBiey" seqno = 32 status = ["RESIZEABLE", "READ", "WRITE"] flags = [] extent_size = 8192 # 4 Megabytes max_lv = 0 max_pv = 0 physical_volumes { pv0 { id = "0usYte-po0G-fR6O-lIm2-bBRl-kMN2-nQhFNu" device = "/dev/md2" # Hint only status = ["ALLOCATABLE"] flags = [] dev_size = 3906493656 # 1.8191 Terabytes pe_start = 384 pe_count = 476866 # 1.8191 Terabytes } } logical_volumes { ... root { id = "oYfRi1-24lV-r6MT-lVKD-ztmK-3dih-jBDVVx" status = ["READ", "WRITE", "VISIBLE"] flags = [] segment_count = 1 segment1 { start_extent = 0 extent_count = 2560 # 10 Gigabytes type = "striped" stripe_count = 1 # linear stripes = [ "pv0", 2048 ] } } ... } }Anhand obiger Sektordaten für 'root' (2097232*4 + 1*4 + 3 + 1 = 16777864):
16777864 = n + pe_start + stripes*extent_size = n + 384 + 2048*8192 n = 264
mythtv2 { id = "aw6EOt-FxCm-I1WW-3GeF-ryTB-nV3b-qypN01" status = ["READ", "WRITE", "VISIBLE"] flags = [] segment_count = 4 segment1 { start_extent = 0 extent_count = 30720 # 120 Gigabytes type = "striped" stripe_count = 1 # linear stripes = [ "pv0", 351488 ] } segment2 { start_extent = 30720 extent_count = 2560 # 10 Gigabytes type = "striped" stripe_count = 1 # linear stripes = [ "pv0", 135168 ] } segment3 { start_extent = 33280 extent_count = 2560 # 10 Gigabytes type = "striped" stripe_count = 1 # linear stripes = [ "pv0", 217088 ] } segment4 { start_extent = 35840 extent_count = 25600 # 100 Gigabytes type = "striped" stripe_count = 1 # linear stripes = [ "pv0", 450048 ] } }führen zu folgenden dd-Aufrufen:
dd if=/dev/md9 bs=512 count=$((30720*8192)) skip=$(($((8192*351488))+264+384)) seek=0 of=mythtv2.dd dd if=/dev/md9 bs=512 count=$((2560*8192)) skip=$(($((8192*135168))+264+384)) seek=$((30720*8192)) of=mythtv2.dd dd if=/dev/md9 bs=512 count=$((2560*8192)) skip=$(($((8192*217088))+264+384)) seek=$((33280*8192)) of=mythtv2.dd dd if=/dev/md9 bs=512 count=$((25600*8192)) skip=$(($((8192*450048))+264+384)) seek=$((35840*8192)) of=mythtv2.dd
Das lässt sich anschließend wieder mit '-o loop' mounten und auslesen.
* testdisk http://www.cgsecurity.org/wiki/TestDisk * http://smartmontools.sourceforge.net/badblockhowto.html#lvm, das hat mich in meine Annahme bestätigt, dass das alles recht linear abgelegt wird * http://www.linuxjournal.com/article/8874?page=0,1 für den Hinweis auf die LVM Metdaten am PV Partitionsanfang