Message ID | 1593782030-521984-6-git-send-email-andrey.shinkevich@virtuozzo.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | iotests: Dump QCOW2 dirty bitmaps metadata | expand |
03.07.2020 16:13, Andrey Shinkevich wrote: > 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 > bitmap_table_offset 0xf0000 > bitmap_table_size 1 > flags 0x2 (['auto']) > 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> > --- > tests/qemu-iotests/291.out | 45 ++++++++++++++++++++++++++++++++++++++ > tests/qemu-iotests/qcow2_format.py | 44 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 89 insertions(+) > > diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out > index 08bfaaa..53a8eeb 100644 > --- a/tests/qemu-iotests/291.out > +++ b/tests/qemu-iotests/291.out > @@ -33,6 +33,24 @@ reserved32 0 > bitmap_directory_size 0x40 > bitmap_directory_offset 0x510000 > > +Bitmap name b1 > +bitmap_table_offset 0x4e0000 > +bitmap_table_size 1 > +flags 0x0 ([]) > +type 1 > +granularity_bits 19 > +name_size 2 > +extra_data_size 0 > + > +Bitmap name b2 > +bitmap_table_offset 0x500000 > +bitmap_table_size 1 > +flags 0x2 (['auto']) > +type 1 > +granularity_bits 16 > +name_size 2 > +extra_data_size 0 > + > > === Bitmap preservation not possible to non-qcow2 === > > @@ -98,6 +116,33 @@ reserved32 0 > bitmap_directory_size 0x60 > bitmap_directory_offset 0x520000 > > +Bitmap name b1 > +bitmap_table_offset 0x470000 > +bitmap_table_size 1 > +flags 0x0 ([]) > +type 1 > +granularity_bits 19 > +name_size 2 > +extra_data_size 0 > + > +Bitmap name b2 > +bitmap_table_offset 0x490000 > +bitmap_table_size 1 > +flags 0x2 (['auto']) > +type 1 > +granularity_bits 16 > +name_size 2 > +extra_data_size 0 > + > +Bitmap name b0 > +bitmap_table_offset 0x510000 > +bitmap_table_size 1 > +flags 0x0 ([]) > +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 d8c058d..7c0dc9a 100644 > --- a/tests/qemu-iotests/qcow2_format.py > +++ b/tests/qemu-iotests/qcow2_format.py > @@ -132,6 +132,50 @@ class Qcow2BitmapExt(Qcow2Struct): > > def __init__(self, fd): > super().__init__(fd=fd) > + self.read_bitmap_directory(fd) > + > + def read_bitmap_directory(self, fd): > + fd.seek(self.bitmap_directory_offset) > + self.bitmap_directory = \ > + [Qcow2BitmapDirEntry(fd) for _ in range(self.nb_bitmaps)] sounds good. I think, we should restore fd position after reading bitmap_directory, to point at the end of extension, to not break further extensions loading > + > + def dump(self): > + super().dump() > + for entry in self.bitmap_directory: > + print() > + entry.dump() > + > + > +class Qcow2BitmapDirEntry(Qcow2Struct): > + > + fields = ( > + ('u64', '{:#x}', 'bitmap_table_offset'), > + ('u32', '{}', 'bitmap_table_size'), > + ('u32', BitmapFlags, 'flags'), > + ('u8', '{}', 'type'), > + ('u8', '{}', 'granularity_bits'), > + ('u16', '{}', 'name_size'), > + ('u32', '{}', 'extra_data_size') > + ) > + > + def __init__(self, fd): > + super().__init__(fd=fd) > + # Seek relative to the current position in the file > + fd.seek(self.extra_data_size, 1) > + bitmap_name = fd.read(self.name_size) > + self.name = bitmap_name.decode('ascii') > + # Move position to the end of the entry in the directory > + entry_raw_size = self.bitmap_dir_entry_raw_size() > + padding = ((entry_raw_size + 7) & ~7) - entry_raw_size > + fd.seek(padding, 1) > + > + def bitmap_dir_entry_raw_size(self): > + return struct.calcsize(self.fmt) + self.name_size + \ > + self.extra_data_size > + > + def dump(self): > + print(f'{"Bitmap name":<25} {self.name}') > + super(Qcow2BitmapDirEntry, self).dump() > > > QCOW2_EXT_MAGIC_BITMAPS = 0x23852875 >
On 11.07.2020 22:11, Vladimir Sementsov-Ogievskiy wrote: > 03.07.2020 16:13, Andrey Shinkevich wrote: >> Read and dump entries from the bitmap directory of QCOW2 image. >> It extends the output in the test case #291. >> >> ... >> diff --git a/tests/qemu-iotests/qcow2_format.py >> b/tests/qemu-iotests/qcow2_format.py >> index d8c058d..7c0dc9a 100644 >> --- a/tests/qemu-iotests/qcow2_format.py >> +++ b/tests/qemu-iotests/qcow2_format.py >> @@ -132,6 +132,50 @@ class Qcow2BitmapExt(Qcow2Struct): >> def __init__(self, fd): >> super().__init__(fd=fd) >> + self.read_bitmap_directory(fd) >> + >> + def read_bitmap_directory(self, fd): >> + fd.seek(self.bitmap_directory_offset) >> + self.bitmap_directory = \ >> + [Qcow2BitmapDirEntry(fd) for _ in range(self.nb_bitmaps)] > > sounds good. I think, we should restore fd position after reading > bitmap_directory, to point at the end of extension, to not break > further extensions loading > > Yes, it is done in the constructor of QcowHeaderExtension: if self.magic == QCOW2_EXT_MAGIC_BITMAPS: ... position = fd.tell() ... self.obj = Qcow2BitmapExt(fd=fd) fd.seek(position) Andrey
13.07.2020 10:07, Andrey Shinkevich wrote: > On 11.07.2020 22:11, Vladimir Sementsov-Ogievskiy wrote: >> 03.07.2020 16:13, Andrey Shinkevich wrote: >>> Read and dump entries from the bitmap directory of QCOW2 image. >>> It extends the output in the test case #291. >>> >>> > ... >>> diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py >>> index d8c058d..7c0dc9a 100644 >>> --- a/tests/qemu-iotests/qcow2_format.py >>> +++ b/tests/qemu-iotests/qcow2_format.py >>> @@ -132,6 +132,50 @@ class Qcow2BitmapExt(Qcow2Struct): >>> def __init__(self, fd): >>> super().__init__(fd=fd) >>> + self.read_bitmap_directory(fd) >>> + >>> + def read_bitmap_directory(self, fd): >>> + fd.seek(self.bitmap_directory_offset) >>> + self.bitmap_directory = \ >>> + [Qcow2BitmapDirEntry(fd) for _ in range(self.nb_bitmaps)] >> >> sounds good. I think, we should restore fd position after reading bitmap_directory, to point at the end of extension, to not break further extensions loading >> >> > Yes, it is done in the constructor of QcowHeaderExtension: > > if self.magic == QCOW2_EXT_MAGIC_BITMAPS: > > ... > > position = fd.tell() > > ... > > self.obj = Qcow2BitmapExt(fd=fd) > > fd.seek(position) > I don't like it. If you want caller to care about fd, caller should know size of created child. But passing fd to constructor implies that caller not aware of size of new created structure. So I think good api is: constuctor starts to read the structure and left after this structure on exit from consturctor (so, caller may read following structures). Constructor may read some nested structures, but is responsible for restoring fd after it.
03.07.2020 16:13, Andrey Shinkevich wrote: > 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 > bitmap_table_offset 0xf0000 > bitmap_table_size 1 > flags 0x2 (['auto']) > 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: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16.07.2020 12:13, Vladimir Sementsov-Ogievskiy wrote: > > Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Oops, sorry, I wanted to answer v10 patch. Ignore this.
diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out index 08bfaaa..53a8eeb 100644 --- a/tests/qemu-iotests/291.out +++ b/tests/qemu-iotests/291.out @@ -33,6 +33,24 @@ reserved32 0 bitmap_directory_size 0x40 bitmap_directory_offset 0x510000 +Bitmap name b1 +bitmap_table_offset 0x4e0000 +bitmap_table_size 1 +flags 0x0 ([]) +type 1 +granularity_bits 19 +name_size 2 +extra_data_size 0 + +Bitmap name b2 +bitmap_table_offset 0x500000 +bitmap_table_size 1 +flags 0x2 (['auto']) +type 1 +granularity_bits 16 +name_size 2 +extra_data_size 0 + === Bitmap preservation not possible to non-qcow2 === @@ -98,6 +116,33 @@ reserved32 0 bitmap_directory_size 0x60 bitmap_directory_offset 0x520000 +Bitmap name b1 +bitmap_table_offset 0x470000 +bitmap_table_size 1 +flags 0x0 ([]) +type 1 +granularity_bits 19 +name_size 2 +extra_data_size 0 + +Bitmap name b2 +bitmap_table_offset 0x490000 +bitmap_table_size 1 +flags 0x2 (['auto']) +type 1 +granularity_bits 16 +name_size 2 +extra_data_size 0 + +Bitmap name b0 +bitmap_table_offset 0x510000 +bitmap_table_size 1 +flags 0x0 ([]) +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 d8c058d..7c0dc9a 100644 --- a/tests/qemu-iotests/qcow2_format.py +++ b/tests/qemu-iotests/qcow2_format.py @@ -132,6 +132,50 @@ class Qcow2BitmapExt(Qcow2Struct): def __init__(self, fd): super().__init__(fd=fd) + self.read_bitmap_directory(fd) + + def read_bitmap_directory(self, fd): + fd.seek(self.bitmap_directory_offset) + self.bitmap_directory = \ + [Qcow2BitmapDirEntry(fd) for _ in range(self.nb_bitmaps)] + + def dump(self): + super().dump() + for entry in self.bitmap_directory: + print() + entry.dump() + + +class Qcow2BitmapDirEntry(Qcow2Struct): + + fields = ( + ('u64', '{:#x}', 'bitmap_table_offset'), + ('u32', '{}', 'bitmap_table_size'), + ('u32', BitmapFlags, 'flags'), + ('u8', '{}', 'type'), + ('u8', '{}', 'granularity_bits'), + ('u16', '{}', 'name_size'), + ('u32', '{}', 'extra_data_size') + ) + + def __init__(self, fd): + super().__init__(fd=fd) + # Seek relative to the current position in the file + fd.seek(self.extra_data_size, 1) + bitmap_name = fd.read(self.name_size) + self.name = bitmap_name.decode('ascii') + # Move position to the end of the entry in the directory + entry_raw_size = self.bitmap_dir_entry_raw_size() + padding = ((entry_raw_size + 7) & ~7) - entry_raw_size + fd.seek(padding, 1) + + def bitmap_dir_entry_raw_size(self): + return struct.calcsize(self.fmt) + self.name_size + \ + self.extra_data_size + + def dump(self): + print(f'{"Bitmap name":<25} {self.name}') + super(Qcow2BitmapDirEntry, self).dump() QCOW2_EXT_MAGIC_BITMAPS = 0x23852875
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 bitmap_table_offset 0xf0000 bitmap_table_size 1 flags 0x2 (['auto']) 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> --- tests/qemu-iotests/291.out | 45 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/qcow2_format.py | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+)