diff mbox series

[v12,07/11] qcow2_format.py: Dump bitmap table serialized entries

Message ID 1596118512-424960-8-git-send-email-andrey.shinkevich@virtuozzo.com
State New
Headers show
Series iotests: Dump QCOW2 dirty bitmaps metadata | expand

Commit Message

Andrey Shinkevich July 30, 2020, 2:15 p.m. UTC
Add bitmap table information to the QCOW2 metadata dump.

Bitmap name               bitmap-1
...
Bitmap table   type            size         offset
0              serialized      65536        10092544
1              all-zeroes      65536        0
2              all-zeroes      65536        0

Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
---
 tests/qemu-iotests/303.out         |  4 ++++
 tests/qemu-iotests/qcow2_format.py | 47 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)

Comments

Vladimir Sementsov-Ogievskiy Aug. 5, 2020, 3:57 p.m. UTC | #1
30.07.2020 17:15, Andrey Shinkevich wrote:
> Add bitmap table information to the QCOW2 metadata dump.
> 
> Bitmap name               bitmap-1
> ...
> Bitmap table   type            size         offset
> 0              serialized      65536        10092544
> 1              all-zeroes      65536        0

For serialized, size and offset are size and offset of bitmap table.
But, all-zeroes bitmaps don't have any bitmap table, so size and offset
both are undefined (OK to print zero for them, but 65536 is unrelated).

> 2              all-zeroes      65536        0
> 
> Signed-off-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
> ---
>   tests/qemu-iotests/303.out         |  4 ++++
>   tests/qemu-iotests/qcow2_format.py | 47 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 51 insertions(+)
> 
> diff --git a/tests/qemu-iotests/303.out b/tests/qemu-iotests/303.out
> index dc3739b..d581fb4 100644
> --- a/tests/qemu-iotests/303.out
> +++ b/tests/qemu-iotests/303.out
> @@ -70,6 +70,8 @@ type                      1
>   granularity_bits          15
>   name_size                 8
>   extra_data_size           0
> +Bitmap table   type            size         offset
> +0              serialized      65536        10092544
>   
>   Bitmap name               bitmap-2
>   bitmap_table_offset       0x9c0000
> @@ -79,4 +81,6 @@ type                      1
>   granularity_bits          16
>   name_size                 8
>   extra_data_size           0
> +Bitmap table   type            size         offset
> +0              all-zeroes      65536        0
>   
> diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py
> index ca0d350..1f033d4 100644
> --- a/tests/qemu-iotests/qcow2_format.py
> +++ b/tests/qemu-iotests/qcow2_format.py
> @@ -175,6 +175,10 @@ class Qcow2BitmapDirEntry(Qcow2Struct):
>           entry_raw_size = self.bitmap_dir_entry_raw_size()
>           padding = ((entry_raw_size + 7) & ~7) - entry_raw_size
>           fd.seek(padding, 1)
> +        self.bitmap_table = Qcow2BitmapTable(fd=fd,
> +                                             offset=self.bitmap_table_offset,
> +                                             nb_entries=self.bitmap_table_size,
> +                                             cluster_size=self.cluster_size)
>   
>       def bitmap_dir_entry_raw_size(self):
>           return struct.calcsize(self.fmt) + self.name_size + \
> @@ -183,6 +187,49 @@ class Qcow2BitmapDirEntry(Qcow2Struct):
>       def dump(self):
>           print(f'{"Bitmap name":<25} {self.name}')
>           super(Qcow2BitmapDirEntry, self).dump()
> +        self.bitmap_table.dump()
> +
> +
> +class Qcow2BitmapTableEntry(Qcow2Struct):
> +
> +    fields = (
> +        ('u64',  '{}', 'entry'),
> +    )
> +
> +    BME_TABLE_ENTRY_RESERVED_MASK = 0xff000000000001fe
> +    BME_TABLE_ENTRY_OFFSET_MASK = 0x00fffffffffffe00
> +    BME_TABLE_ENTRY_FLAG_ALL_ONES = 1
> +
> +    def __init__(self, fd):
> +        super().__init__(fd=fd)
> +        self.reserved = self.entry & self.BME_TABLE_ENTRY_RESERVED_MASK
> +        self.offset = self.entry & self.BME_TABLE_ENTRY_OFFSET_MASK
> +        if self.offset:
> +            if self.entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES:
> +                self.type = 'invalid'
> +            else:
> +                self.type = 'serialized'
> +        elif self.entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES:
> +            self.type = 'all-ones'
> +        else:
> +            self.type = 'all-zeroes'
> +
> +
> +class Qcow2BitmapTable:
> +
> +    def __init__(self, fd, offset, nb_entries, cluster_size):
> +        self.cluster_size = cluster_size
> +        position = fd.tell()
> +        fd.seek(offset)
> +        self.entries = [Qcow2BitmapTableEntry(fd) for _ in range(nb_entries)]
> +        fd.seek(position)
> +
> +    def dump(self):
> +        size = self.cluster_size
> +        bitmap_table = enumerate(self.entries)
> +        print(f'{"Bitmap table":<14} {"type":<15} {"size":<12} {"offset"}')
> +        for i, entry in bitmap_table:
> +            print(f'{i:<14} {entry.type:<15} {size:<12} {entry.offset}')
>   

All this looks like 'cluster_size' is not really needed for Qcow2BitmapTable class (we can print only offsets).
Still, if you want to save it, can we print it only for entries with 'serialized' type?

It's minor, I'm OK with it as is:
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>


>   
>   QCOW2_EXT_MAGIC_BITMAPS = 0x23852875
>
diff mbox series

Patch

diff --git a/tests/qemu-iotests/303.out b/tests/qemu-iotests/303.out
index dc3739b..d581fb4 100644
--- a/tests/qemu-iotests/303.out
+++ b/tests/qemu-iotests/303.out
@@ -70,6 +70,8 @@  type                      1
 granularity_bits          15
 name_size                 8
 extra_data_size           0
+Bitmap table   type            size         offset
+0              serialized      65536        10092544
 
 Bitmap name               bitmap-2
 bitmap_table_offset       0x9c0000
@@ -79,4 +81,6 @@  type                      1
 granularity_bits          16
 name_size                 8
 extra_data_size           0
+Bitmap table   type            size         offset
+0              all-zeroes      65536        0
 
diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py
index ca0d350..1f033d4 100644
--- a/tests/qemu-iotests/qcow2_format.py
+++ b/tests/qemu-iotests/qcow2_format.py
@@ -175,6 +175,10 @@  class Qcow2BitmapDirEntry(Qcow2Struct):
         entry_raw_size = self.bitmap_dir_entry_raw_size()
         padding = ((entry_raw_size + 7) & ~7) - entry_raw_size
         fd.seek(padding, 1)
+        self.bitmap_table = Qcow2BitmapTable(fd=fd,
+                                             offset=self.bitmap_table_offset,
+                                             nb_entries=self.bitmap_table_size,
+                                             cluster_size=self.cluster_size)
 
     def bitmap_dir_entry_raw_size(self):
         return struct.calcsize(self.fmt) + self.name_size + \
@@ -183,6 +187,49 @@  class Qcow2BitmapDirEntry(Qcow2Struct):
     def dump(self):
         print(f'{"Bitmap name":<25} {self.name}')
         super(Qcow2BitmapDirEntry, self).dump()
+        self.bitmap_table.dump()
+
+
+class Qcow2BitmapTableEntry(Qcow2Struct):
+
+    fields = (
+        ('u64',  '{}', 'entry'),
+    )
+
+    BME_TABLE_ENTRY_RESERVED_MASK = 0xff000000000001fe
+    BME_TABLE_ENTRY_OFFSET_MASK = 0x00fffffffffffe00
+    BME_TABLE_ENTRY_FLAG_ALL_ONES = 1
+
+    def __init__(self, fd):
+        super().__init__(fd=fd)
+        self.reserved = self.entry & self.BME_TABLE_ENTRY_RESERVED_MASK
+        self.offset = self.entry & self.BME_TABLE_ENTRY_OFFSET_MASK
+        if self.offset:
+            if self.entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES:
+                self.type = 'invalid'
+            else:
+                self.type = 'serialized'
+        elif self.entry & self.BME_TABLE_ENTRY_FLAG_ALL_ONES:
+            self.type = 'all-ones'
+        else:
+            self.type = 'all-zeroes'
+
+
+class Qcow2BitmapTable:
+
+    def __init__(self, fd, offset, nb_entries, cluster_size):
+        self.cluster_size = cluster_size
+        position = fd.tell()
+        fd.seek(offset)
+        self.entries = [Qcow2BitmapTableEntry(fd) for _ in range(nb_entries)]
+        fd.seek(position)
+
+    def dump(self):
+        size = self.cluster_size
+        bitmap_table = enumerate(self.entries)
+        print(f'{"Bitmap table":<14} {"type":<15} {"size":<12} {"offset"}')
+        for i, entry in bitmap_table:
+            print(f'{i:<14} {entry.type:<15} {size:<12} {entry.offset}')
 
 
 QCOW2_EXT_MAGIC_BITMAPS = 0x23852875