qemu-io - Diagnose und Manipulationen von (virtuellen) Speichermedien
(Link zu dieser Seite als [[QEMU-KVM-Buch/ Speichermedien/ qemu-io]])
Inhaltsverzeichnis |
[bearbeiten] qemu-io
[bearbeiten] Befehle
qemu-io (kvm-io) ist ein Diagnose- und Manipulationsprogramm für (virtuelle) Speichermedien. Es befindet sich noch auf einem frühen Stand der Entwicklung. Mögliche Optionen zeigt -h an.
Host ~$ qemu-io -h Usage: qemu-io [-h] [-V] [-rsnm] [-c cmd] ... [file] QEMU Disk exerciser -c, --cmd command to execute -r, --read-only export read-only -s, --snapshot use snapshot file -n, --nocache disable host cache -g, --growable allow file to grow (only applies to protocols) -m, --misalign misalign allocations for O_DIRECT -k, --native-aio use kernel AIO implementation (on Linux only) -h, --help display this help and exit -V, --version output version information and exit
Wird qemu-io ohne Optionen aufgerufen, gelangt man in den interaktiven Modus. Mit help werden alle internen Befehle aufgelistet.
Host ~$ qemu-io qemu-io> help qemu-io> quit
Soll nur ein interner Befehl ausgeführt werden, wird dieser mit der Option -c direkt aufgerufen.
Host ~$ qemu-io -c help aio_flush -- completes all outstanding aio requests aio_read [-Cqv] [-P pattern ] off len [len..] -- asynchronously reads a number of bytes aio_write [-Cq] [-P pattern ] off len [len..] -- asynchronously writes a number of bytes alloc off [sectors] -- checks if a sector is present in the file close -- close the current open file discard [-Cq] off len -- discards a number of bytes at a specified offset flush -- flush all in-core file state to disk help [command] -- help for one or all commands info -- prints information about the current file length -- gets the length of the current file map -- prints the allocated areas of a file multiwrite [-Cq] [-P pattern ] off len [len..] [; off len [len..]..] -- issues multiple write requests at once open [-Crsn] [path] -- open the file specified by path quit -- exit the program read [-abCpqv] [-P pattern [-s off] [-l len]] off len -- reads a number of bytes at a specified offset readv [-Cqv] [-P pattern ] off len [len..] -- reads a number of bytes at a specified offset truncate off -- truncates the current file at the given offset write [-abCpq] [-P pattern ] off len -- writes a number of bytes at a specified offset writev [-Cq] [-P pattern ] off len [len..] -- writes a number of bytes at a specified offset
Für die folgenden Beispiele benötigt man eine virtuelle Festplatte.
Host ~$ qemu-img create -f qcow2 Platte.img 1G
Das Image wird mit dem Befehl open geöffnet.
Host ~$ qemu-io qemu-io> open Platte.img
Im folgenden Beispiel wird das Image schreibgeschützt geöffnet (-r). Der Host-Cache wird dabei mit -n deaktiviert. Vor der Neueröffnung muss das Image geschlossen werden.
qemu-io> close qemu-io> open -rn Platte.img
Der interne Befehl info zeigt die Größe der Image-Datei an.
qemu-io> length 1 GiB
Informationen über die Image-Datei gibt der interne Befehl info aus.
qemu-io> info format name: qcow2 cluster size: 64 KiB vm state offset: 1 GiB qemu-io> quit
Der interne Befehl open kann entfallen, wenn beim Aufruf von qemu-io der Dateiname mit angegeben wird.
Host ~$ qemu-io -rn Platte.img
Mit map werden die zugewiesenen Bereiche der Image-Datei angezeigt.
qemu-io> map [ 0] 1048576/ 2097152 sectors not allocated at offset 0.000000 bytes (0) [ 536870912] 1048576/ 1048576 sectors not allocated at offset 512 MiB (0)
Der Befehl alloc testet, ob ein bestimmter Sektor in der Datei vorhanden ist.
qemu-io> alloc 0 0/1 sectors allocated at offset 0.000000 bytes qemu-io> alloc 10 offset 10 is not sector aligned
Mit dem Befehl read wird eine Anzahl von Bytes ab dem vorgegebenen Offsett gelesen und in einem Puffer gespeichert. Mit der Option -v wird der Inhalt des Puffers auf die Standard-Ausgabe ausgegeben. In diesem Beispiel wird der Bereich von einem Kilobyte ab dem Offset von 512 Byte auf der Standardausgabe ausgegeben.
qemu-io> read -v 512 1k 00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ...
Eine ähnliche Funktion hat der Befehl discard. Dieser Befehl schreibt aber nicht in den Puffer. In diesem Beispiel wird ein Bereich von einem Kilobyte ab dem Offsett von 512 Bytes ausgelesen.
qemu-io> discard 512 1k discard 1024/1024 bytes at offset 512 1 KiB, 1 ops; 0.0000 sec (244 MiB/sec and 250000.0000 ops/sec)
Sollen ab einem vorgegebenen Offset die Bytes in mehrere Puffer geschrieben werden, ist der Befehl readv anzuwenden. In diesem Beispiel werden zwei Bereiche von jeweils einem Kilobyte ab dem Offset von 512 Byte auf die Standardausgabe ausgegeben.
qemu-io> readv -v 512 1k 1k qemu-io> quit
In den bisherigen Beispielen wurde die Image-Datei nicht verändert. Um die Änderungen vergleichen zu können, ermittelt man erst die aktuelle Größe der Image-Datei.
Host ~$ ls -lh Platte.img -rw-r--r-- 1 ich ich 193K 2011-07-20 11:07 Platte.img Host ~$ qemu-img info Platte.img image: Platte.img file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: 136K cluster_size: 65536
Mit dem Befehl write lassen sich eine Anzahl Bytes ab einem Offset in die Image-Datei schreiben. Optional kann ein Byte-Muster (Default = 0xcdcdcdcd) verwendet werden. In diesem Beispiel wird das Byte-Muster 66 (ACSII-Wert des für B) ab einem Offset von 0 zwei MByte lang geschrieben.
Host ~$ qemu-io -c 'write 0 2M -P 66' Platte.img wrote 2097152/2097152 bytes at offset 0 2 MiB, 1 ops; 0.0000 sec (10.417 MiB/sec and 5.2085 ops/sec) Host ~$ qemu-io -c 'read -v 512 1k' Platte.img 00000200: 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB 00000210: 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 BBBBBBBBBBBBBBBB ...
Die Datei hat sich entsprechend vergrößert, da das Format qcow2 verwendet wurde.
Host ~$ ls -lh Platte.img -rw-r--r-- 1 ich ich 2,4M 2011-07-20 11:27 Platte.img Host ~$ qemu-img info Platte.img image: Platte.img file format: qcow2 virtual size: 1.0G (1073741824 bytes) disk size: 2.2M cluster_size: 65536
Der Befehl writev schreibt aus mehreren Puffern. In diesem Beispiel werden zwei Kilobyte ab dem Offset von 512 Byte in die geöffnete Datei geschrieben.
Host ~$ qemu-io -c 'writev 512 1k 1k' Platte.img wrote 2048/2048 bytes at offset 512 2 KiB, 1 ops; 0.0000 sec (120.453 KiB/sec and 60.2265 ops/sec)
Mehrere Schreibanforderungen sind mit dem Befehl multiwrite möglich. In diesem Beispiel werden zwei Kilobyte ab einem Offset von 512 Bytes und ein Kilobyte ab einem Offset von vier Kilobyte in die geöffnete Datei geschrieben.
Host ~$ qemu-io Platte.img qemu-io> multiwrite 512 1k 1k ; 4k 1k wrote 3072/3072 bytes at offset 512 3 KiB, 1 ops; 0.0000 sec (76.098 KiB/sec and 25.3659 ops/sec)
Asynchrones Lesen und Schreiben ermöglichen die Befehle aio_read und #'aio_write. Mit aio_flush werden alle ausstehenden AIO-Anforderungen vervollständigt. In diesem Beispiel werden zwei Kilobyte ab dem Offset von 512 gelesen und der Puffer auf der Standardausgabe ausgegeben.
qemu-io> aio_read -v 512 1k 1k
In diesem Beispiel werden zwei Kilobyte ab dem Offset von 512 in die Image-Datei geschrieben.
qemu-io> aio_write 512 1k 1k qemu-io> aio_flush qemu-io> quit
Mit dem Befehl truncate schneidet man eine Image-Datei im raw- Format ab dem angegebenen Offset ab.
Host ~$ qemu-img create -f raw Platte.raw 1G Host ~$ ls -lh Platte.raw -rw-r--r-- 1 ich ich 1,0G 2011-07-20 12:00 Platte.raw Host ~$ qemu-img info Platte.raw image: Platte.raw file format: raw virtual size: 1.0G (1073741824 bytes) disk size: 0
In diesem Beispiel wird die Image-Date ab dem Offset von 512 Byte abgeschnitten.
Host ~$ qemu-io -c 'truncate 512' Platte.raw Host ~$ ls -lh Platte.raw -rw-r--r-- 1 ich ich 512 2011-07-20 12:01 Platte.raw Host ~$ qemu-img info Platte.raw image: Platte.raw file format: raw virtual size: 512 (512 bytes) disk size: 0
[bearbeiten] Anwendungsbeispiele
[bearbeiten] I/O-Fehler-Injektionen
Zum Debuggen sind mitunter I/O-Fehler-Injektionen notwendig. Dies wird von dem Block-Treiber und Protokoll blkdebug unterstützt. Die Textdatei blkdebug.cfg zur Konfiguration der I/O-Fehler wird angelegt.
# blkdebug.cfg [inject-error] event = "l1_update" errno = "5" immediately = "on"
Es wird eine virtuelle Festplatte generiert. Diese wird mit der Angabe des Protokolls blkdebug und der Konfigurationsdate von qemu-img aufgerufen. Bei Schreibvorgängen werden Fehler angezeigt.
Host ~$ qemu-img create -f raw Platte.img 1G Host ~$ qemu-io blkdebug:blkdebug.cfg:Platte.img Host ~$ qemu-io -c 'write 0 1k' blkdebug:blkdebug.cfg:Platte.img write failed: Input/output error
[bearbeiten] Testen von Block-Treibern
blkverify ist ein Protokoll zum Testen von Block-Treibern. Das Problem beim Debuggen ist, das durch Lesefehler des Block-Treibers dieser selbst beeinträchtig wird. blkverify löst dieses Problem in dem die Lesefehler innerhalb von QEMU abgefangen und die entsprechenden Sektoren als korrupt gemeldet werden. Das Protokoll blkverify besitzt dazu zwei Child-Block-Devices. Zum einen ist es das Test-Device und zum anderen das Raw-Device. Lese- und Schreibvorgänge werden parallel auf beiden Devices ausgeführt und die Ergebnisse verglichen. Das Raw-Image verarbeitet die Lese- und Schreibvorgänge korrekt und dient als Referenz für das Test-Image. Nach jedem Lese- und Schreibvorgang vergleicht blkverify die Daten und meldet Abweichungen als korrupte Daten.
Zur Verdeutlichung generiert man zwei Images.
Host ~$ qemu-img create -f raw Platte-raw.img 1G Host ~$ qemu-img create -f qcow2 Platte-qcow2.img 1G
Öffnet man beide Images in qemu-io mit dem Protokoll blkverify werden keine Lesefehler angezeigt.
Host ~$ qemu-io -c 'read 0 256' blkverify:Platte-raw.img:Platte-qcow2.img read 256/256 bytes at offset 0 256.000000 bytes, 1 ops; 0.0000 sec (1.938 MiB/sec and 7936.5079 ops/sec)
Das zweite Image wird mit qemu-io manipuliert.
Host ~$ qemu-io -c 'write 0 512' Platte-qcow2.img wrote 512/512 bytes at offset 0 512.000000 bytes, 1 ops; 0.0000 sec (9.059 KiB/sec and 18.1179 ops/sec)
Durch die Unterschiede werden Fehler gemeldet.
Host ~$ qemu-io -c 'read 0 512' blkverify:Platte-raw.img:Platte-qcow2.img blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0
Ein realistischeres Szenario ist die Überprüfung der Installation eines Gast-Systems.
Host ~$ qemu-img create -f raw Platte-raw.img 16G Host ~$ qemu-img create -f qcow2 Platte-qcow2.img 16G Host ~$ qemu-system-x86_64 -cdrom ReactOS.iso \ -drive file=blkverify:Platte-raw.img:Platte-qcow2.img
Wenn die Installation abbricht, da blkverify Fehler festgestellt hat, sollte man mit qemu-io den Inhalt des Disk-Image überprüfen.