orm@doc-tcpip.org | Erstellt: August 2007 - Letzte Modifikation: März 2008 |
Gemeinhin wird unter der Bezeichnis "VGDA" alles zusammengefaßt, was an Informationen vom LVM auf eine Platte gelegt wird, wenn diese in eine VG aufgenommen wird. Das sind aber mehrere Teile, die nicht unbedingt redundant auf der Platte liegen. So gibt es den LVM Record (LVM_REC) pro Platte nur einmal im Block 7. Die anderen Teile (VGSA und VGDA) sind an zwei Stellen vorhanden. Dabei kommt es darauf an, was für eine Art von VG gebaut worden ist.
Die genauen Informationen zur Lage finden sich im LVM_REC. Das Format ist im Header File /usr/include/lvmrec.h festgelegt. Dieser Block wird auf die Platte geschrieben, wenn sie in eine VG aufgenommen wird.
Zum informativem auslesen gibt es unter AIX ein Kommando: /usr/sbin/readvgda. Der Aufruf geht gegen das hdisk-Device:
# /usr/sbin/readvgda /dev/hdisk0 | moreMit dem Kommando kann man auch für einzelne LV Maps erstellen. Dieses Kommando liest immer den ersten VGDA aus. Sollte man Probleme mit dem Quorum haben, dann müßte man den zweiten VGDA von Hand bearbeiten, wie unten gezeigt.
Das Problem ist jetzt, das AIX sehr konservativ ist, was das Schreiben der Information auf den Platten angeht. Mit regulären Kommandos ist eigentlich nur ein Abgleich von der Platte in die ODM möglich (synclvodm). Die VGDAs lassen sich im Prinzip nur durch das Anlegen eines Dummy-LV tatsächlich auf die Platten schreiben, was nur bei kleineren Problemen hilft.
Will man Teile der Information modifizieren (weil sie durch irgendwelche Wunder dritter Ordnung verstrubbelt worden sind), dann muß man mit dem dd-Kommando die relevanten Teile von der Platte ziehen, in einem Hex-Editor ändern und per dd wieder zurücklegen.
Dieses Vorgehen wird dann nötig, wenn nicht die gesamte Information auf allen Platten inkonsistent ist (da hilft das Dummy-LV mit implizitem Neuschreiben des VGDA aller Platten), sondern eine Platte aus der Reihe fällt.
Welche Blocks man ausliest, ergibt sich aus der Ausgabe des readvgda Kommandos bzw. aus dem LVM_REC. Nützlich ist da das Redbook "LVM A-Z", da sind die Blöcke beschrieben.
Auslesen des Blocks 7, in dem der LVM_REC steht: dd if=/dev/hdisk4 of=/tmp/hdisk4.blk7 count=1 skip=7 Die binäre Datei läßt sich mit dem od-Kommando in Hex darstellen: root@dumpy:/root # od -x /tmp/hdisk4.blk7 0000000 5f4c 564d 00c6 a02f 0000 4c00 0000 0115 0000020 dccc aefd 0000 466a 0000 21ea 0000 0180 0000040 0000 2500 07ff 6a7f 0000 0100 0001 001c 0000060 0000 0100 0000 0080 0000 2400 001e 0000 0000100 0000 0000 0000 0000 0000 0000 0000 0000 * 0001000 od -x gibt hexadezimale 2-Byte Einheiten. Vorne werden die Zeilen in Oktal gezählt. Die Bytes sind also so nummeriert: ByteNr. 0 1 2 3 4 5 6 7 8 10 12 14 9 11 13 15 0000000 5f4c 564d 00c6 a02f 0000 4c00 0000 0115 0000020 Und 20 oktal == 16 dezimal 0001000 1000 oktal == 512 dezimal, also 1 Block In /usr/include/lvmrec.h findet sich das Layout für den LVM Record. Zur Verwirrung werden hier die Bytes wieder in Hex gezählt, und zwar vom Offset der nutzbaren Platte (E00 == 3540 Byte, 3548/512 = 7, also sind wir im Block 7). Das ist der LVM_REC für eine "Standard-VG": /* Old LVM record layout 00000E00 LVM___ID VGID__W1 VGID__W2 VGID__W3 00000E10 VGID__W4 AREA_LEN VGDA_LEN VGDAPSN0 00000E20 VGDAPSN1 RELOCPSN RELOCLEN PVnmPPsh 00000E30 VGSA_LEN VGSAPSN0 VGSAPSN1 VERnTYPE 00000E40 LTG_SIZE RESERVED RESERVED RESERVED 00000E50 RESERVED RESERVED RESERVED RESERVED ... 00000FF0 RESERVED RESERVED RESERVED RESERVED */ Eine neue, scalable VG hat so einen LVM_REC: /* LVM record layout 00000E00 LVM___ID VGID__W1 VGID__W2 VGID__W3 00000E10 VGID__W4 PPSA_LEN PVM__LEN MWCDBLEN 00000E20 VGI__LEN PVI__LEN LVCBILEN LVEA_LEN 00000E30 PPEA_LEN RESA_LEN PV___NUM VERnPPSZ 00000E40 PPSAPSN0 PPSAPSN0 PPSAPSN1 PPSAPSN1 00000E50 PVM_PSN0 PVM_PSN0 PVM_PSN1 PVM_PSN1 00000E60 MWC_PSN0 MWC_PSN0 MWC_PSN1 MWC_PSN1 00000E70 VGI_PSN0 VGI_PSN0 VGI_PSN1 VGI_PSN1 00000E80 PVI_PSN0 PVI_PSN0 PVI_PSN1 PVI_PSN1 00000E90 LVCBPSN0 LVCBPSN0 LVCBPSN1 LVCBPSN1 00000EA0 LVEAPSN0 LVEAPSN0 LVEAPSN1 LVEAPSN1 00000EB0 PPEAPSN0 PPEAPSN0 PPEAPSN1 PPEAPSN1 00000EC0 VGSAPSN0 VGSAPSN0 VGSAPSN1 VGSAPSN1 00000ED0 VGDAPSN0 VGDAPSN0 VGDAPSN1 VGDAPSN1 00000EE0 VGSA_LEN VGDA_LEN LTG_SIZE BBR__LEN 00000EF0 BBR_PSN0 BBR_PSN0 RESERVED RESERVED ... 00000FF0 RESERVED RESERVED RESERVED RESERVED */ Die einzelnen Felder sind jeweils in Wörtern, also 2 Byte. So ergibt sich: LVM_ID == 5f4c 564d Das ist immer so, es ist "_LVM" in ASCII. Die VGID sind 4 Wörter: VGID == 00c6 a02f 0000 4c00 0000 0115 dccc aefd Das deckt sich jetzt alles ganz wunderbar mit der Ausgabe des LVM_REC aus readvgda (man kann also ganz sorgenlos dieses Kommando benutzen): lvmid: 1598838349 (5f4c564d) => LVM___ID vgid: 00c6a02f00004c0000000115dcccaefd => VGID__W1 - W4 lvmarea_len: 18026 => AREA_LEN vgda_len: 8682 => VGDA_LEN vgda_psn[0]: 384 => VGDAPSN0 vgda_psn[1]: 9472 => VGDAPSN1 reloc_psn: 134179455 => RELOCPSN pv_num: 1 => PVnmPPsh pp_size: 28 => PVnmPPsh vgsa_len: 256 => VGSA_LEN vgsa_psn[0]: 128 => VGSAPSN0 vgsa_psn[1]: 9216 => VGSAPSN1 version: 30 => VERnTYPE vg_type: 0 => VERnTYPE ltg_shift: 0(128K) => LTG_SIZE Auf diese Weise findet man jetzt auch die Lage von VGDA und VGSA - wo es losgeht, zeigen diese Einträge, jeweils für 1. und 2. Kopie. Das ist der Block, wo VGDA und VGSA beginnen: vgda_psn[0]: 384 vgda_psn[1]: 9472 vgsa_psn[0]: 128 vgsa_psn[1]: 9216 Dann muß man nur noch herausfinden, wieviel man auslesen muß. Das sind folgende Werte in Byte: vgda_len: 8682 vgsa_len: 256 Die Werte teilt man durch 512 (ein Block, und man muß auf volle Blöcke aufrunden). Das ist der Count für das dd-Kommando. Will man also die beiden VGDAs der Platte: dd if=/dev/hdisk4 of=/tmp/hdisk4.vgda1 count=17 skip=384 dd if=/dev/hdisk4 of=/tmp/hdisk4.vgda2 count=17 skip=9472 Sinngemäß dasselbe für den VGSA, wobei der nur einen halben Block lang ist. dd if=/dev/hdisk4 of=/tmp/hdisk4.vgsa1 count=1 skip=128 dd if=/dev/hdisk4 of=/tmp/hdisk4.vgsa2 count=1 skip=9216 root@dumpy:/tmp # od -x hdisk4.vgsa1 0000000 479f 60f4 20ba c8bc 0000 0000 0000 0000 0000020 0000 0000 0000 0000 0000 0000 0000 0000 * 0001000 Das ist der Zeitstempel in dezimalen Sekunden seit Epoch, dann das Feld mit den Stale-Flags pro PP. Wenn man nun hoffentlich einen Fehler identifiziert hat, kann man den entsprechenden Teil von LVM_REC, VGSA oder VGDA mit einem Hex-Editor editieren (z.B. khex im KDE). Das Ergebniss mutig mit dem dd-Kommando zurückschreiben und freuen...
***************************************** LVMREC at block 7 ***************************************** lvmid: 1598838349 (5f4c564d) vgid: 00c6a02f00004c0000000115dcccaefd lvmarea_len: 18026 vgda_len: 8682 vgda_psn[0]: 384 vgda_psn[1]: 9472 reloc_psn: 134179455 pv_num: 1 pp_size: 28 vgsa_len: 256 vgsa_psn[0]: 128 vgsa_psn[1]: 9216 version: 30 vg_type: 0 ltg_shift: 0(128K)Das ist der LVM_REC, den gibt es, wie schon gesagt, nur einmal auf jeder Platte. Die lvmid ist immer gleich, die VGID die der VG - die muß in allen LVM_RECs und VGDAs aller Platten gleich sein. Wichtig sind die Größen und Offsets des VGSA und des VGDA: Länge vgsa_len, Offset für 1. VGSA vgsa_psn[0], Offset für 2. VGSA vgsa_psn[1]. Analog für den VGDA. Eine genaue Beschreibung der Felder gibt es in /usr/include/lvmrec.h.
*=============== 1ST VGDA-VGSA: /dev/hdisk4 ===============* ***************************************** VGSA at block 128 ***************************************** ***************************************** vgsa beg: timestamp 1196161260 (474bf8ec), 620686730 (24feed8a) vgsa beg: timestamp Tue Nov 27 12:01:00 MEZ:2007 vgsa.pv_missing: 0 vgsa.stalepp[0]: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vgsa.stalepp[1]: 0 fe 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vgsa.stalepp[2]: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vgsa.stalepp[3]: 0 fe 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vgsa.factor: 1 vgsa.pad2: 0 0 0 lv_dirty_bit: 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| vgsa end: timestamp 1196161260 (474bf8ec), 620686730 (24feed8a) vgsa end: timestamp Tue Nov 27 12:01:00 MEZ:2007Das ist jetzt der VGSA. Er beginnt mit dem Zeitstempel, dann folgt ein Flag, das gesetzt wird, wenn ein PV in der VG fehlt. Dann folgen die Felder mit den Flags für Stale PPs. Der VGSA Faktor ist die Folge, wenn man eine VG mit dem "t-Faktor" anlegt und so das Feld für die Flags vergrößert. Dann ein Feld, indem Dirty-Flags für nicht synchronisierte LV gesetzt werden können. Zum Schluß nochmal ein Zeitstempel.
***************************************** VGDA at block 384 ***************************************** ***************************************** vgh.vg_id: 00c6a02f00004c0000000115dcccaefd vgh.numlvs: 2 vgh.maxlvs: 512 vgh.pp_size: 28 vgh.numpvs: 4 vgh.total_vgdas: 4 vgh.bigda_size: 8682 vgh.vgtype: 1 vgh.quorum: 0 vgh.auto_varyon: 0 vgh.check_sum: 0 vgh.snapshotvg: 0 vgh.snapshot_copy: 0 vgh.primary_vgid: 00000000000000000000000000000000 vgh.seconadary_vgid: 00000000000000000000000000000000 vgda hdr: timestamp 1196161665 (474bfa81), 357995727 (155694cf) vgda hdr: timestamp Tue Nov 27 12:07:45 MEZ:2007Die Daten der VG: VGID, PP Size, Typ der VG, Anzahl der PV, die die VG bilden, Anzahl der LV. Beim Typ der VG sind folgende Werte möglich: 0 = OldVG, 1 = BigVG, 2 = Scalable VG.
********** Logical Volume: maestrofta1lv *********** lv_entries.lvname: 0 lv_entries.maxsize: 512 lv_entries.lv_state: 1 lv_entries.mirror: 2 lv_entries.mirror_policy: 2 lv_entries.num_lps: 4 lv_entries.permissions: 1 lv_entries.bb_relocation: 1 lv_entries.write_veryfy: 2 lv_entries.mirwrt_consist: 1 lv_entries.stripe_exp: 0 lv_entries.striping_width: 0 lv_entries.lv_avoid: 0 lv_entries.child_minor_num: 0 lv_entries.dev_uid: 0 lv_entries.dev_gid: 0 lv_entries.dev_perm: 432 lv_entries.lvcb.type: jfs2 lv_entries.lvcb.created_time: Fri Oct 26 16:52:54 2007 lv_entries.lvcb.modified_time: Fri Oct 26 16:53:06 2007 lv_entries.lvcb.relocatable: y lv_entries.lvcb.interpolicy: m lv_entries.lvcb.intrapolicy: m lv_entries.lvcb.strict: s lv_entries.lvcb.upperbound: 2 lv_entries.lvcb.label: /applications/maestro1 lv_entries.lvcb.fs: vfs=jfs2:log=INLINE:type=db1:account=false ********** Logical Volume: tivoli_lcf_a_lv *********** lv_entries.lvname: 1 lv_entries.maxsize: 512 lv_entries.lv_state: 1 lv_entries.mirror: 2 lv_entries.mirror_policy: 2 lv_entries.num_lps: 1 lv_entries.permissions: 1 lv_entries.bb_relocation: 1 lv_entries.write_veryfy: 2 lv_entries.mirwrt_consist: 1 lv_entries.stripe_exp: 0 lv_entries.striping_width: 0 lv_entries.lv_avoid: 0 lv_entries.child_minor_num: 0 lv_entries.dev_uid: 0 lv_entries.dev_gid: 0 lv_entries.dev_perm: 432 lv_entries.lvcb.type: jfs2 lv_entries.lvcb.created_time: Fri Oct 26 16:52:58 2007 lv_entries.lvcb.modified_time: Fri Oct 26 16:53:13 2007 lv_entries.lvcb.relocatable: y lv_entries.lvcb.interpolicy: m lv_entries.lvcb.intrapolicy: m lv_entries.lvcb.strict: s lv_entries.lvcb.upperbound: 2 lv_entries.lvcb.label: /opt/Tivoli/lcf_A lv_entries.lvcb.fs: vfs=jfs2:log=INLINE:type=db1:account=falseFür jedes der zwei vorhanden LV folgt ein Control-Block mit den wichtigen Daten zum LV.
********** Physical Volume: 1 *********** pvh.pv_num: 1 pvh.pv_id: 00c6a02fdccca6a4 pvh.pp_count: 255 pvh.pv_state: 1 pvh.pvnum_vgdas: 1 pvh.psn_part1: 18176 * pv_num:pp_num:pp_state lv_name:lp_num:pp_copy_val:pv_fst_mir:part_fst_mir:pv_snd_mir:part_snd_mir * pv1: 2:1 maestrofta1lv:3:1:2:2:0:0 * pv1: 3:1 maestrofta1lv:4:1:2:3:0:0Jetzt kommt pro PV ein Datensatz: Logische Nummer des PV, PVID, Anzahl PP, Status des PV. Die Nummern dazu findet man in /usr/include/lvm.h ( 0 = not defined, 1 = aktive, 2 = PV missing, 4 = PV removed, 16 = PV stale etc.). Dann folgt die PP-Map der LV, die auf dieser Platten Daten haben.
********** Physical Volume: 2 *********** pvh.pv_num: 2 pvh.pv_id: 00c6a02fdccca8fc pvh.pp_count: 255 pvh.pv_state: 1 pvh.pvnum_vgdas: 1 pvh.psn_part1: 18176 * pv_num:pp_num:pp_state lv_name:lp_num:pp_copy_val:pv_fst_mir:part_fst_mir:pv_snd_mir:part_snd_mir * pv2: 2:1 maestrofta1lv:3:2:1:2:0:0 * pv2: 3:1 maestrofta1lv:4:2:1:3:0:0 ********** Physical Volume: 3 *********** pvh.pv_num: 3 pvh.pv_id: 00c6a02fdcccab41 pvh.pp_count: 255 pvh.pv_state: 1 pvh.pvnum_vgdas: 1 pvh.psn_part1: 18176 * pv_num:pp_num:pp_state lv_name:lp_num:pp_copy_val:pv_fst_mir:part_fst_mir:pv_snd_mir:part_snd_mir * pv3: 2:1 maestrofta1lv:1:1:4:2:0:0 * pv3: 3:1 maestrofta1lv:2:1:4:3:0:0 * pv3: 4:1 tivoli_lcf_a_lv:1:1:4:4:0:0 ********** Physical Volume: 4 *********** pvh.pv_num: 4 pvh.pv_id: 00c6a02fdcccae29 pvh.pp_count: 255 pvh.pv_state: 1 pvh.pvnum_vgdas: 1 pvh.psn_part1: 18176 * pv_num:pp_num:pp_state lv_name:lp_num:pp_copy_val:pv_fst_mir:part_fst_mir:pv_snd_mir:part_snd_mir * pv4: 2:1 maestrofta1lv:1:2:3:2:0:0 * pv4: 3:1 maestrofta1lv:2:2:3:3:0:0 * pv4: 4:1 tivoli_lcf_a_lv:1:2:3:4:0:0
***************************************** vgt.concurrency: 32 vgda trl: timestamp 1196161665 (474bfa81), 357995727 (155694cf) vgda trl: timestamp Tue Nov 27 12:07:45 MEZ:2007Am Ende noch ein Zeitstempel.
[ Allgemein | UNIX | AIX | TCP-IP | TCP | ROUTING | DNS | NTP | NFS | FreeBSD | Linux | RPi | SMTP | Tracing | GPS | LW ]
Copyright 2001-2021 by Orm Hager - Es gilt die GPL