From: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, vsementsov@virtuozzo.com,
qemu-devel@nongnu.org, mreitz@redhat.com,
andrey.shinkevich@virtuozzo.com, den@openvz.org
Subject: [PATCH v7 4/9] qcow2_format.py: Dump bitmap directory information
Date: Fri, 12 Jun 2020 03:04:57 +0300 [thread overview]
Message-ID: <1591920302-1002219-5-git-send-email-andrey.shinkevich@virtuozzo.com> (raw)
In-Reply-To: <1591920302-1002219-1-git-send-email-andrey.shinkevich@virtuozzo.com>
Read and dump entries from the bitmap directory of QCOW2 image.
It extends the output in the test case #291.
Header extension:
magic 0x23852875 (Bitmaps)
...
Bitmap name bitmap-1
flag auto
table size 8 (bytes)
bitmap_table_offset 0x90000
bitmap_table_size 1
flags 0
type 1
granularity_bits 16
name_size 8
extra_data_size 0
Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
tests/qemu-iotests/291.out | 52 ++++++++++++++++++++++++++
tests/qemu-iotests/qcow2_format.py | 75 ++++++++++++++++++++++++++++++++++++++
2 files changed, 127 insertions(+)
diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out
index ccfcdc5..d847419 100644
--- a/tests/qemu-iotests/291.out
+++ b/tests/qemu-iotests/291.out
@@ -33,6 +33,27 @@ reserved32 0
bitmap_directory_size 0x40
bitmap_directory_offset 0x510000
+Bitmap name b1
+table size 8 (bytes)
+bitmap_table_offset 0x4e0000
+bitmap_table_size 1
+flags 0
+type 1
+granularity_bits 19
+name_size 2
+extra_data_size 0
+
+Bitmap name b2
+flag auto
+table size 8 (bytes)
+bitmap_table_offset 0x500000
+bitmap_table_size 1
+flags 2
+type 1
+granularity_bits 16
+name_size 2
+extra_data_size 0
+
=== Bitmap preservation not possible to non-qcow2 ===
@@ -98,6 +119,37 @@ reserved32 0
bitmap_directory_size 0x60
bitmap_directory_offset 0x520000
+Bitmap name b1
+table size 8 (bytes)
+bitmap_table_offset 0x470000
+bitmap_table_size 1
+flags 0
+type 1
+granularity_bits 19
+name_size 2
+extra_data_size 0
+
+Bitmap name b2
+flag auto
+table size 8 (bytes)
+bitmap_table_offset 0x490000
+bitmap_table_size 1
+flags 2
+type 1
+granularity_bits 16
+name_size 2
+extra_data_size 0
+
+Bitmap name b0
+table size 8 (bytes)
+bitmap_table_offset 0x510000
+bitmap_table_size 1
+flags 0
+type 1
+granularity_bits 16
+name_size 2
+extra_data_size 0
+
=== Check bitmap contents ===
diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py
index d4f0000..90eff92 100644
--- a/tests/qemu-iotests/qcow2_format.py
+++ b/tests/qemu-iotests/qcow2_format.py
@@ -103,6 +103,10 @@ class Qcow2Struct(metaclass=Qcow2StructMeta):
print('{:<25} {}'.format(f[2], value_str))
+# seek relative to the current position in the file
+FROM_CURRENT = 1
+
+
class Qcow2BitmapExt(Qcow2Struct):
fields = (
@@ -112,6 +116,73 @@ class Qcow2BitmapExt(Qcow2Struct):
('u64', '{:#x}', 'bitmap_directory_offset')
)
+ def read_bitmap_directory(self, fd):
+ self.bitmaps = []
+ fd.seek(self.bitmap_directory_offset)
+ buf_size = struct.calcsize(Qcow2BitmapDirEntry.fmt)
+
+ for n in range(self.nb_bitmaps):
+ buf = fd.read(buf_size)
+ dir_entry = Qcow2BitmapDirEntry(data=buf)
+ fd.seek(dir_entry.extra_data_size, FROM_CURRENT)
+ bitmap_name = fd.read(dir_entry.name_size)
+ dir_entry.name = bitmap_name.decode('ascii')
+ self.bitmaps.append(dir_entry)
+ entry_raw_size = dir_entry.bitmap_dir_entry_raw_size()
+ shift = ((entry_raw_size + 7) & ~7) - entry_raw_size
+ fd.seek(shift, FROM_CURRENT)
+
+ def load(self, fd):
+ self.read_bitmap_directory(fd)
+
+ def dump(self):
+ super().dump()
+ for bm in self.bitmaps:
+ bm.dump_bitmap_dir_entry()
+
+
+BME_FLAG_IN_USE = 1 << 0
+BME_FLAG_AUTO = 1 << 1
+
+
+class Qcow2BitmapDirEntry(Qcow2Struct):
+
+ name = ''
+
+ fields = (
+ ('u64', '{:#x}', 'bitmap_table_offset'),
+ ('u32', '{}', 'bitmap_table_size'),
+ ('u32', '{}', 'flags'),
+ ('u8', '{}', 'type'),
+ ('u8', '{}', 'granularity_bits'),
+ ('u16', '{}', 'name_size'),
+ ('u32', '{}', 'extra_data_size')
+ )
+
+ def __init__(self, data):
+ super().__init__(data=data)
+
+ self.bitmap_table_bytes = self.bitmap_table_size \
+ * struct.calcsize('Q')
+
+ self.bitmap_flags = []
+ if (self.flags & BME_FLAG_IN_USE):
+ self.bitmap_flags.append("in-use")
+ if (self.flags & BME_FLAG_AUTO):
+ self.bitmap_flags.append("auto")
+
+ def bitmap_dir_entry_raw_size(self):
+ return struct.calcsize(self.fmt) + self.name_size + \
+ self.extra_data_size
+
+ def dump_bitmap_dir_entry(self):
+ print()
+ print(f'{"Bitmap name":<25} {self.name}')
+ for fl in self.bitmap_flags:
+ print(f'{"flag":<25} {fl}')
+ print(f'{"table size":<25} {self.bitmap_table_bytes} {"(bytes)"}')
+ super().dump()
+
QCOW2_EXT_MAGIC_BITMAPS = 0x23852875
@@ -253,6 +324,10 @@ class QcowHeader(Qcow2Struct):
else:
self.extensions.append(ext)
+ for ext in self.extensions:
+ if ext.obj is not None:
+ ext.obj.load(fd)
+
def update_extensions(self, fd):
fd.seek(self.header_length)
--
1.8.3.1
next prev parent reply other threads:[~2020-06-12 0:06 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-12 0:04 [PATCH v7 0/9] iotests: Dump QCOW2 dirty bitmaps metadata Andrey Shinkevich
2020-06-12 0:04 ` [PATCH v7 1/9] iotests: Fix for magic hexadecimal output in 291 Andrey Shinkevich
2020-06-15 9:43 ` Vladimir Sementsov-Ogievskiy
2020-06-12 0:04 ` [PATCH v7 2/9] qcow2: Fix capitalization of header extension constant Andrey Shinkevich
2020-06-15 9:44 ` Vladimir Sementsov-Ogievskiy
2020-06-12 0:04 ` [PATCH v7 3/9] qcow2_format.py: make printable data an extension class member Andrey Shinkevich
2020-06-15 9:47 ` Vladimir Sementsov-Ogievskiy
2020-06-12 0:04 ` Andrey Shinkevich [this message]
2020-06-15 10:34 ` [PATCH v7 4/9] qcow2_format.py: Dump bitmap directory information Vladimir Sementsov-Ogievskiy
2020-06-12 0:04 ` [PATCH v7 5/9] qcow2_format.py: pass cluster size to substructures Andrey Shinkevich
2020-06-12 0:04 ` [PATCH v7 6/9] qcow2_format.py: Dump bitmap table serialized entries Andrey Shinkevich
2020-06-12 0:05 ` [PATCH v7 7/9] qcow2.py: Introduce '-j' key to dump in JSON format Andrey Shinkevich
2020-06-12 0:05 ` [PATCH v7 8/9] qcow2_format.py: collect fields " Andrey Shinkevich
2020-06-12 0:05 ` [PATCH v7 9/9] qcow2_format.py: support dumping metadata " Andrey Shinkevich
2020-06-15 9:42 ` [PATCH v7 0/9] iotests: Dump QCOW2 dirty bitmaps metadata Vladimir Sementsov-Ogievskiy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1591920302-1002219-5-git-send-email-andrey.shinkevich@virtuozzo.com \
--to=andrey.shinkevich@virtuozzo.com \
--cc=den@openvz.org \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).